diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index 7676ff716c418503dcdb7a09fdc36c9eba6a47f8..190dd1e5ba5af0f7e0cfba49d3dcae5bf27cf978 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -272,7 +272,7 @@ if [[ "${linux_projects}" != "" ]]; then artifact_paths: - 'artifacts/**/*' - '*_result.json' - - 'build/test-results.xml' + - 'build/test-results.*.xml' agents: ${LINUX_AGENTS} retry: automatic: @@ -295,7 +295,7 @@ if [[ "${windows_projects}" != "" ]]; then artifact_paths: - 'artifacts/**/*' - '*_result.json' - - 'build/test-results.xml' + - 'build/test-results.*.xml' agents: ${WINDOWS_AGENTS} retry: automatic: diff --git a/.ci/generate_test_report.py b/.ci/generate_test_report.py new file mode 100644 index 0000000000000000000000000000000000000000..237f45e6f08e06376af3ca310bb7fc4409cb32cd --- /dev/null +++ b/.ci/generate_test_report.py @@ -0,0 +1,423 @@ +# Script to parse many JUnit XML result files and send a report to the buildkite +# agent as an annotation. +# +# To run the unittests: +# python3 -m unittest discover -p generate_test_report.py + +import argparse +import subprocess +import unittest +from io import StringIO +from junitparser import JUnitXml, Failure +from textwrap import dedent + + +def junit_from_xml(xml): + return JUnitXml.fromfile(StringIO(xml)) + + +class TestReports(unittest.TestCase): + def test_title_only(self): + self.assertEqual(_generate_report("Foo", []), ("", None)) + + def test_no_tests_in_testsuite(self): + self.assertEqual( + _generate_report( + "Foo", + [ + junit_from_xml( + dedent( + """\ + + + + + """ + ) + ) + ], + ), + ("", None), + ) + + def test_no_failures(self): + self.assertEqual( + _generate_report( + "Foo", + [ + junit_from_xml( + dedent( + """\ + + + + + + """ + ) + ) + ], + ), + ( + dedent( + """\ + # Foo + + * 1 test passed""" + ), + "success", + ), + ) + + def test_report_single_file_single_testsuite(self): + self.assertEqual( + _generate_report( + "Foo", + [ + junit_from_xml( + dedent( + """\ + + + + + + + + + + + + + + + """ + ) + ) + ], + ), + ( + dedent( + """\ + # Foo + + * 1 test passed + * 1 test skipped + * 2 tests failed + + ## Failed Tests + (click to see output) + + ### Bar +
+ Bar/test_3/test_3 + + ``` + Output goes here + ``` +
+
+ Bar/test_4/test_4 + + ``` + Other output goes here + ``` +
""" + ), + "error", + ), + ) + + MULTI_SUITE_OUTPUT = ( + dedent( + """\ + # ABC and DEF + + * 1 test passed + * 1 test skipped + * 2 tests failed + + ## Failed Tests + (click to see output) + + ### ABC +
+ ABC/test_2/test_2 + + ``` + ABC/test_2 output goes here + ``` +
+ + ### DEF +
+ DEF/test_2/test_2 + + ``` + DEF/test_2 output goes here + ``` +
""" + ), + "error", + ) + + def test_report_single_file_multiple_testsuites(self): + self.assertEqual( + _generate_report( + "ABC and DEF", + [ + junit_from_xml( + dedent( + """\ + + + + + + + + + + + + + + + + + """ + ) + ) + ], + ), + self.MULTI_SUITE_OUTPUT, + ) + + def test_report_multiple_files_multiple_testsuites(self): + self.assertEqual( + _generate_report( + "ABC and DEF", + [ + junit_from_xml( + dedent( + """\ + + + + + + + + + """ + ) + ), + junit_from_xml( + dedent( + """\ + + + + + + + + + + + """ + ) + ), + ], + ), + self.MULTI_SUITE_OUTPUT, + ) + + def test_report_dont_list_failures(self): + self.assertEqual( + _generate_report( + "Foo", + [ + junit_from_xml( + dedent( + """\ + + + + + + + + """ + ) + ) + ], + list_failures=False, + ), + ( + dedent( + """\ + # Foo + + * 1 test failed + + Failed tests and their output was too large to report. Download the build's log file to see the details.""" + ), + "error", + ), + ) + + def test_report_size_limit(self): + self.assertEqual( + _generate_report( + "Foo", + [ + junit_from_xml( + dedent( + """\ + + + + + + + + """ + ) + ) + ], + size_limit=128, + ), + ( + dedent( + """\ + # Foo + + * 1 test failed + + Failed tests and their output was too large to report. Download the build's log file to see the details.""" + ), + "error", + ), + ) + + +# Set size_limit to limit the byte size of the report. The default is 1MB as this +# is the most that can be put into an annotation. If the generated report exceeds +# this limit and failures are listed, it will be generated again without failures +# listed. This minimal report will always fit into an annotation. +# If include failures is False, total number of test will be reported but their names +# and output will not be. +def _generate_report(title, junit_objects, size_limit=1024 * 1024, list_failures=True): + if not junit_objects: + return ("", "success") + + failures = {} + tests_run = 0 + tests_skipped = 0 + tests_failed = 0 + + for results in junit_objects: + for testsuite in results: + tests_run += testsuite.tests + tests_skipped += testsuite.skipped + tests_failed += testsuite.failures + + for test in testsuite: + if ( + not test.is_passed + and test.result + and isinstance(test.result[0], Failure) + ): + if failures.get(testsuite.name) is None: + failures[testsuite.name] = [] + failures[testsuite.name].append( + (test.classname + "/" + test.name, test.result[0].text) + ) + + if not tests_run: + return ("", style) + + style = "error" if tests_failed else "success" + report = [f"# {title}", ""] + + tests_passed = tests_run - tests_skipped - tests_failed + + def plural(num_tests): + return "test" if num_tests == 1 else "tests" + + if tests_passed: + report.append(f"* {tests_passed} {plural(tests_passed)} passed") + if tests_skipped: + report.append(f"* {tests_skipped} {plural(tests_skipped)} skipped") + if tests_failed: + report.append(f"* {tests_failed} {plural(tests_failed)} failed") + + if not list_failures: + report.extend( + [ + "", + "Failed tests and their output was too large to report. " + "Download the build's log file to see the details.", + ] + ) + elif failures: + report.extend(["", "## Failed Tests", "(click to see output)"]) + + for testsuite_name, failures in failures.items(): + report.extend(["", f"### {testsuite_name}"]) + for name, output in failures: + report.extend( + [ + "
", + f"{name}", + "", + "```", + output, + "```", + "
", + ] + ) + + report = "\n".join(report) + if len(report.encode("utf-8")) > size_limit: + return _generate_report(title, junit_objects, size_limit, list_failures=False) + + return report, style + + +def generate_report(title, junit_files): + return _generate_report(title, [JUnitXml.fromfile(p) for p in junit_files]) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "title", help="Title of the test report, without Markdown formatting." + ) + parser.add_argument("context", help="Annotation context to write to.") + parser.add_argument("junit_files", help="Paths to JUnit report files.", nargs="*") + args = parser.parse_args() + + report, style = generate_report(args.title, args.junit_files) + + if report: + p = subprocess.Popen( + [ + "buildkite-agent", + "annotate", + "--context", + args.context, + "--style", + style, + ], + stdin=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + ) + + # The report can be larger than the buffer for command arguments so we send + # it over stdin instead. + _, err = p.communicate(input=report) + if p.returncode: + raise RuntimeError(f"Failed to send report to buildkite-agent:\n{err}") diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index b78dc59432b65c9dcdf5130fe6aea85fb2d03148..a4aeea7a16addc4206bf046a8f828f567af68bda 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -28,18 +28,26 @@ if [[ -n "${CLEAR_CACHE:-}" ]]; then ccache --clear fi -function show-stats { +function at-exit { mkdir -p artifacts ccache --print-stats > artifacts/ccache_stats.txt + + # If building fails there will be no results files. + shopt -s nullglob + python3 "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":linux: Linux x64 Test Results" \ + "linux-x64-test-results" "${BUILD_DIR}"/test-results.*.xml } -trap show-stats EXIT +trap at-exit EXIT projects="${1}" targets="${2}" +lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests" + echo "--- cmake" pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt pip install -q -r "${MONOREPO_ROOT}"/lldb/test/requirements.txt +pip install -q -r "${MONOREPO_ROOT}"/.ci/requirements.txt cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ @@ -47,7 +55,7 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_ASSERTIONS=ON \ -D LLVM_BUILD_EXAMPLES=ON \ -D COMPILER_RT_BUILD_LIBFUZZER=OFF \ - -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --timeout=1200 --time-tests" \ + -D LLVM_LIT_ARGS="${lit_args}" \ -D LLVM_ENABLE_LLD=ON \ -D CMAKE_CXX_FLAGS=-gmlt \ -D LLVM_CCACHE_BUILD=ON \ @@ -87,7 +95,8 @@ if [[ "${runtimes}" != "" ]]; then -D CMAKE_BUILD_TYPE=RelWithDebInfo \ -D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ -D LIBCXX_TEST_PARAMS="std=c++03" \ - -D LIBCXXABI_TEST_PARAMS="std=c++03" + -D LIBCXXABI_TEST_PARAMS="std=c++03" \ + -D LLVM_LIT_ARGS="${lit_args}" echo "--- ninja runtimes C++03" @@ -104,7 +113,8 @@ if [[ "${runtimes}" != "" ]]; then -D CMAKE_BUILD_TYPE=RelWithDebInfo \ -D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ -D LIBCXX_TEST_PARAMS="std=c++26" \ - -D LIBCXXABI_TEST_PARAMS="std=c++26" + -D LIBCXXABI_TEST_PARAMS="std=c++26" \ + -D LLVM_LIT_ARGS="${lit_args}" echo "--- ninja runtimes C++26" @@ -121,7 +131,8 @@ if [[ "${runtimes}" != "" ]]; then -D CMAKE_BUILD_TYPE=RelWithDebInfo \ -D CMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ -D LIBCXX_TEST_PARAMS="enable_modules=clang" \ - -D LIBCXXABI_TEST_PARAMS="enable_modules=clang" + -D LIBCXXABI_TEST_PARAMS="enable_modules=clang" \ + -D LLVM_LIT_ARGS="${lit_args}" echo "--- ninja runtimes clang modules" diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 91e719c52d43632e73112e4e1a8b286af492c21b..4ead122212f4f04be414e20b0a2f0c34e4f4a6ea 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -27,17 +27,23 @@ if [[ -n "${CLEAR_CACHE:-}" ]]; then fi sccache --zero-stats -function show-stats { +function at-exit { mkdir -p artifacts sccache --show-stats >> artifacts/sccache_stats.txt + + # If building fails there will be no results files. + shopt -s nullglob + python "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":windows: Windows x64 Test Results" \ + "windows-x64-test-results" "${BUILD_DIR}"/test-results.*.xml } -trap show-stats EXIT +trap at-exit EXIT projects="${1}" targets="${2}" echo "--- cmake" pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt +pip install -q -r "${MONOREPO_ROOT}"/.ci/requirements.txt # The CMAKE_*_LINKER_FLAGS to disable the manifest come from research # on fixing a build reliability issue on the build server, please @@ -53,7 +59,7 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_ASSERTIONS=ON \ -D LLVM_BUILD_EXAMPLES=ON \ -D COMPILER_RT_BUILD_LIBFUZZER=OFF \ - -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --timeout=1200 --time-tests" \ + -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests" \ -D COMPILER_RT_BUILD_ORC=OFF \ -D CMAKE_C_COMPILER_LAUNCHER=sccache \ -D CMAKE_CXX_COMPILER_LAUNCHER=sccache \ diff --git a/.ci/requirements.txt b/.ci/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..ad63858c9fdc2c7b7b61fe42a67059c1ddd46ce2 --- /dev/null +++ b/.ci/requirements.txt @@ -0,0 +1 @@ +junitparser==3.2.0 diff --git a/.github/new-issues-labeler.yml b/.github/new-issues-labeler.yml index a5933d7fc9b37244828e63265ab9feb2426cdb52..860535bbe3083528dad66e64ba0045681b4ad4d3 100644 --- a/.github/new-issues-labeler.yml +++ b/.github/new-issues-labeler.yml @@ -27,3 +27,6 @@ 'bolt': - '/\bbolt(?!\-)\b/i' + +'infra:commit-access-request': + - '/Request Commit Access/' diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml index c6746779d2dca632259552d6186dfb464ecd43d5..54290f15419d9a8d0289b3581f7797567cb3bd1e 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -587,6 +587,12 @@ 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/** diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml index 2184ddd49537b57c48ae0ad55c4829e60cc91083..472d18e73da78d63df3c30698bcb8159670c9ef6 100644 --- a/.github/workflows/libcxx-build-and-test.yaml +++ b/.github/workflows/libcxx-build-and-test.yaml @@ -45,12 +45,11 @@ env: LLVM_SYMBOLIZER_PATH: "/usr/bin/llvm-symbolizer-19" CLANG_CRASH_DIAGNOSTICS_DIR: "crash_diagnostics" - jobs: stage1: if: github.repository_owner == 'llvm' - runs-on: libcxx-runners-set - container: ghcr.io/libcxx/actions-builder:testing-2024-09-21 + runs-on: libcxx-self-hosted-linux + container: ghcr.io/llvm/libcxx-linux-builder:0fd6f684b9c84c32d6cbfd9742402e788b2879f1 continue-on-error: false strategy: fail-fast: false @@ -86,8 +85,8 @@ jobs: **/crash_diagnostics/* stage2: if: github.repository_owner == 'llvm' - runs-on: libcxx-runners-set - container: ghcr.io/libcxx/actions-builder:testing-2024-09-21 + runs-on: libcxx-self-hosted-linux + container: ghcr.io/llvm/libcxx-linux-builder:0fd6f684b9c84c32d6cbfd9742402e788b2879f1 needs: [ stage1 ] continue-on-error: false strategy: @@ -161,21 +160,21 @@ jobs: 'generic-static', 'bootstrapping-build' ] - machine: [ 'libcxx-runners-set' ] + machine: [ 'libcxx-self-hosted-linux' ] include: - config: 'generic-cxx26' - machine: libcxx-runners-set + machine: libcxx-self-hosted-linux - config: 'generic-asan' - machine: libcxx-runners-set + machine: libcxx-self-hosted-linux - config: 'generic-tsan' - machine: libcxx-runners-set + machine: libcxx-self-hosted-linux - config: 'generic-ubsan' - machine: libcxx-runners-set + machine: libcxx-self-hosted-linux # Use a larger machine for MSAN to avoid timeout and memory allocation issues. - config: 'generic-msan' - machine: libcxx-runners-set + machine: libcxx-self-hosted-linux runs-on: ${{ matrix.machine }} - container: ghcr.io/libcxx/actions-builder:testing-2024-09-21 + container: ghcr.io/llvm/libcxx-linux-builder:0fd6f684b9c84c32d6cbfd9742402e788b2879f1 steps: - uses: actions/checkout@v4 - name: ${{ matrix.config }} @@ -202,13 +201,13 @@ jobs: matrix: include: - config: generic-cxx03 - os: macos-latest + os: macos-15 - config: generic-cxx23 - os: macos-latest + os: macos-15 - config: generic-modules - os: macos-latest + os: macos-15 - config: apple-configuration - os: macos-latest + os: macos-15 - config: apple-system os: macos-13 - config: apple-system-hardened diff --git a/.github/workflows/libcxx-build-containers.yml b/.github/workflows/libcxx-build-containers.yml new file mode 100644 index 0000000000000000000000000000000000000000..2d040f712ce592b1190cfbdc5a8aeb1190ba1613 --- /dev/null +++ b/.github/workflows/libcxx-build-containers.yml @@ -0,0 +1,71 @@ +# 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 + packages: write + +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-latest + if: github.repository_owner == 'llvm' + permissions: + packages: write + + steps: + - uses: actions/checkout@v4 + + - 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@v3 + 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/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index 08ce892054874c1f842c096f9a12f1f0ae415a39..c9b0e103ed5145b6841f25c651e7ac6e4a39165e 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -723,12 +723,28 @@ public: /// Stats for stale profile matching: /// the total number of basic blocks in the profile uint32_t NumStaleBlocks{0}; - /// the number of matched basic blocks - uint32_t NumMatchedBlocks{0}; + /// the number of exactly matched basic blocks + uint32_t NumExactMatchedBlocks{0}; + /// the number of loosely matched basic blocks + uint32_t NumLooseMatchedBlocks{0}; + /// the number of exactly pseudo probe matched basic blocks + uint32_t NumPseudoProbeExactMatchedBlocks{0}; + /// the number of loosely pseudo probe matched basic blocks + uint32_t NumPseudoProbeLooseMatchedBlocks{0}; + /// the number of call matched basic blocks + uint32_t NumCallMatchedBlocks{0}; /// the total count of samples in the profile uint64_t StaleSampleCount{0}; - /// the count of matched samples - uint64_t MatchedSampleCount{0}; + /// the count of exactly matched samples + uint64_t ExactMatchedSampleCount{0}; + /// the count of loosely matched samples + uint64_t LooseMatchedSampleCount{0}; + /// the count of exactly pseudo probe matched samples + uint64_t PseudoProbeExactMatchedSampleCount{0}; + /// the count of loosely pseudo probe matched samples + uint64_t PseudoProbeLooseMatchedSampleCount{0}; + /// the count of call matched samples + uint64_t CallMatchedSampleCount{0}; /// the number of stale functions that have matching number of blocks in /// the profile uint64_t NumStaleFuncsWithEqualBlockCount{0}; diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h index d362961176b3262d259110562373eee30316f703..1093f6ad78a99016cd94a5f074282c7b39f6119a 100644 --- a/bolt/include/bolt/Core/BinarySection.h +++ b/bolt/include/bolt/Core/BinarySection.h @@ -87,6 +87,7 @@ class BinarySection { // been renamed) uint64_t OutputAddress{0}; // Section address for the rewritten binary. uint64_t OutputSize{0}; // Section size in the rewritten binary. + // Can exceed OutputContents with padding. uint64_t OutputFileOffset{0}; // File offset in the rewritten binary file. StringRef OutputContents; // Rewritten section contents. const uint64_t SectionNumber; // Order in which the section was created. @@ -474,6 +475,11 @@ public: /// Use name \p SectionName for the section during the emission. void emitAsData(MCStreamer &Streamer, const Twine &SectionName) const; + /// Write finalized contents of the section. If OutputSize exceeds the size of + /// the OutputContents, append zero padding to the stream and return the + /// number of byte written which should match the OutputSize. + uint64_t write(raw_ostream &OS) const; + using SymbolResolverFuncTy = llvm::function_ref; /// Flush all pending relocations to patch original contents of sections @@ -497,6 +503,9 @@ public: IsFinalized = true; } + /// When writing section contents, add \p PaddingSize zero bytes at the end. + void addPadding(uint64_t PaddingSize) { OutputSize += PaddingSize; } + /// Reorder the contents of this section according to /p Order. If /// /p Inplace is true, the entire contents of the section is reordered, /// otherwise the new contents contain only the reordered data. diff --git a/bolt/include/bolt/Core/Exceptions.h b/bolt/include/bolt/Core/Exceptions.h index 422b86f6ddb7a3ac5709cb2644c034526b1626e2..f10cf776f09437f0b89a3a70aac73e692cfa8fec 100644 --- a/bolt/include/bolt/Core/Exceptions.h +++ b/bolt/include/bolt/Core/Exceptions.h @@ -43,17 +43,14 @@ public: /// Generate .eh_frame_hdr from old and new .eh_frame sections. /// - /// Take FDEs from the \p NewEHFrame unless their initial_pc is listed - /// in \p FailedAddresses. All other entries are taken from the + /// Take FDEs from the \p NewEHFrame. All other entries are taken from the /// \p OldEHFrame. /// /// \p EHFrameHeaderAddress specifies location of .eh_frame_hdr, /// and is required for relative addressing used in the section. - std::vector - generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame, - const DWARFDebugFrame &NewEHFrame, - uint64_t EHFrameHeaderAddress, - std::vector &FailedAddresses) const; + std::vector generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame, + const DWARFDebugFrame &NewEHFrame, + uint64_t EHFrameHeaderAddress) const; using FDEsMap = std::map; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 32eda0b283b883bc91487eb3472d9b2a44219e88..3634fed9757ceb9c7e898f09c88bd18ef0c6df73 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -1536,6 +1536,14 @@ public: llvm_unreachable("not implemented"); } + /// Match function \p BF to a long veneer for absolute code. Return true if + /// the match was successful and populate \p TargetAddress with an address of + /// the function veneer jumps to. + virtual bool matchAbsLongVeneer(const BinaryFunction &BF, + uint64_t &TargetAddress) const { + llvm_unreachable("not implemented"); + } + virtual bool matchAdrpAddPair(const MCInst &Adrp, const MCInst &Add) const { llvm_unreachable("not implemented"); return false; diff --git a/bolt/include/bolt/Profile/ProfileYAMLMapping.h b/bolt/include/bolt/Profile/ProfileYAMLMapping.h index 9865118f2696d3a2c78a5f742a0e774cd9a754d4..a8c9f7a10bbb90ad21c11bc5045839a69c9d053d 100644 --- a/bolt/include/bolt/Profile/ProfileYAMLMapping.h +++ b/bolt/include/bolt/Profile/ProfileYAMLMapping.h @@ -174,6 +174,9 @@ struct InlineTreeNode { uint32_t CallSiteProbe; // Index in PseudoProbeDesc.GUID, UINT32_MAX for same as previous (omitted) uint32_t GUIDIndex; + // Decoded contents, ParentIndexDelta becomes absolute value. + uint64_t GUID; + uint64_t Hash; bool operator==(const InlineTreeNode &) const { return false; } }; } // end namespace bolt diff --git a/bolt/include/bolt/Profile/YAMLProfileReader.h b/bolt/include/bolt/Profile/YAMLProfileReader.h index a6f0fd6f3251f0debfc509efe72d4dad4518775b..91f51f30e3ca45ac5433b64df7d2f417c5c346df 100644 --- a/bolt/include/bolt/Profile/YAMLProfileReader.h +++ b/bolt/include/bolt/Profile/YAMLProfileReader.h @@ -14,6 +14,8 @@ #include namespace llvm { +class MCDecodedPseudoProbeInlineTree; + namespace bolt { class YAMLProfileReader : public ProfileReaderBase { @@ -43,6 +45,9 @@ public: using ProfileLookupMap = DenseMap; + using GUIDInlineTreeMap = + std::unordered_map; + /// A class for matching binary functions in functions in the YAML profile. /// First, a call graph is constructed for both profiled and binary functions. /// Then functions are hashed based on the names of their callee/caller @@ -96,6 +101,61 @@ public: YamlBFAdjacencyMap; }; + // A class for matching inline tree nodes between profile and binary. + // Provides the mapping from profile inline tree node id to a + // corresponding binary MCDecodedPseudoProbeInlineTree node. + // + // The whole mapping process is the following: + // + // (profile) (binary) + // | blocks ^ + // v | + // yaml::bolt::BinaryBasicBlockProfile ~= FlowBlock + // ||| probes ^ (majority vote) + // v ||| BBPseudoProbeToBlock + // yaml::bolt::PseudoProbeInfo MCDecodedPseudoProbe + // | InlineTreeIndex ^ + // v | probe id + // [ profile node id (uint32_t) -> MCDecodedPseudoProbeInlineTree *] + // InlineTreeNodeMapTy + class InlineTreeNodeMapTy { + DenseMap Map; + + void mapInlineTreeNode(uint32_t ProfileNodeIdx, + const MCDecodedPseudoProbeInlineTree *BinaryNode) { + auto Res = Map.try_emplace(ProfileNodeIdx, BinaryNode); + assert(Res.second && + "Duplicate mapping from profile node index to binary inline tree"); + (void)Res; + } + + public: + /// Returns matched InlineTree * for a given profile inline_tree_id. + const MCDecodedPseudoProbeInlineTree * + getInlineTreeNode(uint32_t ProfileInlineTreeNodeId) const { + auto It = Map.find(ProfileInlineTreeNodeId); + if (It == Map.end()) + return nullptr; + return It->second; + } + + // Match up \p YamlInlineTree with binary inline tree rooted at \p Root. + // Return the number of matched nodes. + // + // This function populates the mapping from profile inline tree node id to a + // corresponding binary MCDecodedPseudoProbeInlineTree node. + size_t matchInlineTrees( + const MCPseudoProbeDecoder &Decoder, + const std::vector &YamlInlineTree, + const MCDecodedPseudoProbeInlineTree *Root); + }; + + // Partial probe matching specification: matched inline tree and corresponding + // BinaryFunctionProfile + using ProbeMatchSpec = + std::pair>; + private: /// Adjustments for basic samples profiles (without LBR). bool NormalizeByInsnCount{false}; @@ -129,6 +189,13 @@ private: /// BinaryFunction pointers indexed by YamlBP functions. std::vector ProfileBFs; + // Pseudo probe function GUID to inline tree node + GUIDInlineTreeMap TopLevelGUIDToInlineTree; + + // Mapping from a binary function to its partial match specification + // (YAML profile and its inline tree mapping to binary). + DenseMap> BFToProbeMatchSpecs; + /// Populate \p Function profile with the one supplied in YAML format. bool parseFunctionProfile(BinaryFunction &Function, const yaml::bolt::BinaryFunctionProfile &YamlBF); @@ -139,7 +206,8 @@ private: /// Infer function profile from stale data (collected on older binaries). bool inferStaleProfile(BinaryFunction &Function, - const yaml::bolt::BinaryFunctionProfile &YamlBF); + const yaml::bolt::BinaryFunctionProfile &YamlBF, + const ArrayRef ProbeMatchSpecs); /// Initialize maps for profile matching. void buildNameMaps(BinaryContext &BC); @@ -156,6 +224,10 @@ private: /// Matches functions using the call graph. size_t matchWithCallGraph(BinaryContext &BC); + /// Matches functions using the call graph. + /// Populates BF->partial probe match spec map. + size_t matchWithPseudoProbes(BinaryContext &BC); + /// Matches functions with similarly named profiled functions. size_t matchWithNameSimilarity(BinaryContext &BC); diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h index e5b7ad63007cab4294b986b256b2603d64253fb5..73d2857f946cce1cb82290ae5b3b97330bfdbfb1 100644 --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -556,14 +556,6 @@ private: return ErrOrSection ? &ErrOrSection.get() : nullptr; } - /// Keep track of functions we fail to write in the binary. We need to avoid - /// rewriting CFI info for these functions. - std::vector FailedAddresses; - - /// Keep track of which functions didn't fit in their original space in the - /// last emission, so that we may either decide to split or not optimize them. - std::set LargeFunctions; - /// Section header string table. StringTableBuilder SHStrTab; diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index f6dfa249f9a9f54217b39eb399b184dcc2197acc..4b5d8154728ccd7dbd03defa6f85b94f5f5ad5dd 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -416,17 +416,6 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF, BF.duplicateConstantIslands(); } - if (!FF.empty() && FF.front()->isLandingPad()) { - assert(!FF.front()->isEntryPoint() && - "Landing pad cannot be entry point of function"); - // If the first block of the fragment is a landing pad, it's offset from the - // start of the area that the corresponding LSDA describes is zero. In this - // case, the call site entries in that LSDA have 0 as offset to the landing - // pad, which the runtime interprets as "no handler". To prevent this, - // insert some padding. - Streamer.emitBytes(BC.MIB->getTrapFillValue()); - } - // Track the first emitted instruction with debug info. bool FirstInstr = true; for (BinaryBasicBlock *const BB : FF) { @@ -906,17 +895,6 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { if (Sites.empty()) return; - // Calculate callsite table size. Size of each callsite entry is: - // - // sizeof(start) + sizeof(length) + sizeof(LP) + sizeof(uleb128(action)) - // - // or - // - // sizeof(dwarf::DW_EH_PE_data4) * 3 + sizeof(uleb128(action)) - uint64_t CallSiteTableLength = llvm::size(Sites) * 4 * 3; - for (const auto &FragmentCallSite : Sites) - CallSiteTableLength += getULEB128Size(FragmentCallSite.second.Action); - Streamer.switchSection(BC.MOFI->getLSDASection()); const unsigned TTypeEncoding = BF.getLSDATypeEncoding(); @@ -937,74 +915,79 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { // Emit the LSDA header. // If LPStart is omitted, then the start of the FDE is used as a base for - // landing pad displacements. Then if a cold fragment starts with - // a landing pad, this means that the first landing pad offset will be 0. - // As a result, the exception handling runtime will ignore this landing pad - // because zero offset denotes the absence of a landing pad. - // For this reason, when the binary has fixed starting address we emit LPStart - // as 0 and output the absolute value of the landing pad in the table. + // landing pad displacements. Then, if a cold fragment starts with a landing + // pad, this means that the first landing pad offset will be 0. However, C++ + // runtime treats 0 as if there is no landing pad present, thus we *must* emit + // non-zero offsets for all valid LPs. // - // If the base address can change, we cannot use absolute addresses for - // landing pads (at least not without runtime relocations). Hence, we fall - // back to emitting landing pads relative to the FDE start. - // As we are emitting label differences, we have to guarantee both labels are - // defined in the same section and hence cannot place the landing pad into a - // cold fragment when the corresponding call site is in the hot fragment. - // Because of this issue and the previously described issue of possible - // zero-offset landing pad we have to place landing pads in the same section - // as the corresponding invokes for shared objects. + // As a solution, for fixed-address binaries we set LPStart to 0, and for + // position-independent binaries we set LP start to FDE start minus one byte + // for FDEs that start with a landing pad. + const bool NeedsLPAdjustment = !FF.empty() && FF.front()->isLandingPad(); std::function emitLandingPad; if (BC.HasFixedLoadAddress) { Streamer.emitIntValue(dwarf::DW_EH_PE_udata4, 1); // LPStart format Streamer.emitIntValue(0, 4); // LPStart emitLandingPad = [&](const MCSymbol *LPSymbol) { - if (!LPSymbol) - Streamer.emitIntValue(0, 4); - else + if (LPSymbol) Streamer.emitSymbolValue(LPSymbol, 4); + else + Streamer.emitIntValue(0, 4); }; } else { - Streamer.emitIntValue(dwarf::DW_EH_PE_omit, 1); // LPStart format + if (NeedsLPAdjustment) { + // Use relative LPStart format and emit LPStart as [SymbolStart - 1]. + Streamer.emitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1); + MCSymbol *DotSymbol = BC.Ctx->createTempSymbol("LPBase"); + Streamer.emitLabel(DotSymbol); + + const MCExpr *LPStartExpr = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(StartSymbol, *BC.Ctx), + MCSymbolRefExpr::create(DotSymbol, *BC.Ctx), *BC.Ctx); + LPStartExpr = MCBinaryExpr::createSub( + LPStartExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx); + Streamer.emitValue(LPStartExpr, 4); + } else { + // DW_EH_PE_omit means FDE start (StartSymbol) will be used as LPStart. + Streamer.emitIntValue(dwarf::DW_EH_PE_omit, 1); + } emitLandingPad = [&](const MCSymbol *LPSymbol) { - if (!LPSymbol) - Streamer.emitIntValue(0, 4); - else - Streamer.emitAbsoluteSymbolDiff(LPSymbol, StartSymbol, 4); + if (LPSymbol) { + const MCExpr *LPOffsetExpr = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(LPSymbol, *BC.Ctx), + MCSymbolRefExpr::create(StartSymbol, *BC.Ctx), *BC.Ctx); + if (NeedsLPAdjustment) + LPOffsetExpr = MCBinaryExpr::createAdd( + LPOffsetExpr, MCConstantExpr::create(1, *BC.Ctx), *BC.Ctx); + Streamer.emitULEB128Value(LPOffsetExpr); + } else { + Streamer.emitULEB128IntValue(0); + } }; } Streamer.emitIntValue(TTypeEncoding, 1); // TType format - // See the comment in EHStreamer::emitExceptionTable() on to use - // uleb128 encoding (which can use variable number of bytes to encode the same - // value) to ensure type info table is properly aligned at 4 bytes without - // iteratively fixing sizes of the tables. - unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength); - unsigned TTypeBaseOffset = - sizeof(int8_t) + // Call site format - CallSiteTableLengthSize + // Call site table length size - CallSiteTableLength + // Call site table length - BF.getLSDAActionTable().size() + // Actions table size - BF.getLSDATypeTable().size() * TTypeEncodingSize; // Types table size - unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset); - unsigned TotalSize = sizeof(int8_t) + // LPStart format - sizeof(int8_t) + // TType format - TTypeBaseOffsetSize + // TType base offset size - TTypeBaseOffset; // TType base offset - unsigned SizeAlign = (4 - TotalSize) & 3; + MCSymbol *TTBaseLabel = nullptr; + if (TTypeEncoding != dwarf::DW_EH_PE_omit) { + TTBaseLabel = BC.Ctx->createTempSymbol("TTBase"); + MCSymbol *TTBaseRefLabel = BC.Ctx->createTempSymbol("TTBaseRef"); + Streamer.emitAbsoluteSymbolDiffAsULEB128(TTBaseLabel, TTBaseRefLabel); + Streamer.emitLabel(TTBaseRefLabel); + } - if (TTypeEncoding != dwarf::DW_EH_PE_omit) - // Account for any extra padding that will be added to the call site table - // length. - Streamer.emitULEB128IntValue(TTypeBaseOffset, - /*PadTo=*/TTypeBaseOffsetSize + SizeAlign); + // Emit encoding of entries in the call site table. The format is used for the + // call site start, length, and corresponding landing pad. + if (BC.HasFixedLoadAddress) + Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1); + else + Streamer.emitIntValue(dwarf::DW_EH_PE_uleb128, 1); - // Emit the landing pad call site table. We use signed data4 since we can emit - // a landing pad in a different part of the split function that could appear - // earlier in the address space than LPStart. - Streamer.emitIntValue(dwarf::DW_EH_PE_sdata4, 1); - Streamer.emitULEB128IntValue(CallSiteTableLength); + MCSymbol *CSTStartLabel = BC.Ctx->createTempSymbol("CSTStart"); + MCSymbol *CSTEndLabel = BC.Ctx->createTempSymbol("CSTEnd"); + Streamer.emitAbsoluteSymbolDiffAsULEB128(CSTEndLabel, CSTStartLabel); + Streamer.emitLabel(CSTStartLabel); for (const auto &FragmentCallSite : Sites) { const BinaryFunction::CallSite &CallSite = FragmentCallSite.second; const MCSymbol *BeginLabel = CallSite.Start; @@ -1015,11 +998,17 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { // Start of the range is emitted relative to the start of current // function split part. - Streamer.emitAbsoluteSymbolDiff(BeginLabel, StartSymbol, 4); - Streamer.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4); + if (BC.HasFixedLoadAddress) { + Streamer.emitAbsoluteSymbolDiff(BeginLabel, StartSymbol, 4); + Streamer.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4); + } else { + Streamer.emitAbsoluteSymbolDiffAsULEB128(BeginLabel, StartSymbol); + Streamer.emitAbsoluteSymbolDiffAsULEB128(EndLabel, BeginLabel); + } emitLandingPad(CallSite.LP); Streamer.emitULEB128IntValue(CallSite.Action); } + Streamer.emitLabel(CSTEndLabel); // Write out action, type, and type index tables at the end. // @@ -1038,6 +1027,8 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { assert(TypeTable.size() == BF.getLSDATypeTable().size() && "indirect type table size mismatch"); + Streamer.emitValueToAlignment(Align(TTypeAlignment)); + for (int Index = TypeTable.size() - 1; Index >= 0; --Index) { const uint64_t TypeAddress = TypeTable[Index]; switch (TTypeEncoding & 0x70) { @@ -1063,6 +1054,10 @@ void BinaryEmitter::emitLSDA(BinaryFunction &BF, const FunctionFragment &FF) { } } } + + if (TTypeEncoding != dwarf::DW_EH_PE_omit) + Streamer.emitLabel(TTBaseLabel); + for (uint8_t const &Byte : BF.getLSDATypeIndexTable()) Streamer.emitIntValue(Byte, 1); } diff --git a/bolt/lib/Core/BinarySection.cpp b/bolt/lib/Core/BinarySection.cpp index 9ad49ca1b3a03832a31d77aad54e89dfa850e3dc..b16e0a4333aa2d7000ff47d92c6035bb5fc07d67 100644 --- a/bolt/lib/Core/BinarySection.cpp +++ b/bolt/lib/Core/BinarySection.cpp @@ -142,6 +142,15 @@ void BinarySection::emitAsData(MCStreamer &Streamer, Streamer.emitLabel(BC.Ctx->getOrCreateSymbol("__hot_data_end")); } +uint64_t BinarySection::write(raw_ostream &OS) const { + const uint64_t NumValidContentBytes = + std::min(getOutputContents().size(), getOutputSize()); + OS.write(getOutputContents().data(), NumValidContentBytes); + if (getOutputSize() > NumValidContentBytes) + OS.write_zeros(getOutputSize() - NumValidContentBytes); + return getOutputSize(); +} + void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS, SymbolResolverFuncTy Resolver) { if (PendingRelocations.empty() && Patches.empty()) diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp index 6a46a49a983d8b5797bc8111fc7b89a13ee0d987..0b2e63b8ca6a790af4219122b24714d44b8664bc 100644 --- a/bolt/lib/Core/Exceptions.cpp +++ b/bolt/lib/Core/Exceptions.cpp @@ -108,8 +108,7 @@ Error BinaryFunction::parseLSDA(ArrayRef LSDASectionData, DWARFDataExtractor Data( StringRef(reinterpret_cast(LSDASectionData.data()), LSDASectionData.size()), - BC.DwCtx->getDWARFObj().isLittleEndian(), - BC.DwCtx->getDWARFObj().getAddressSize()); + BC.AsmInfo->isLittleEndian(), BC.AsmInfo->getCodePointerSize()); uint64_t Offset = getLSDAAddress() - LSDASectionAddress; assert(Data.isValidOffset(Offset) && "wrong LSDA address"); @@ -666,16 +665,13 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const { return true; } -std::vector CFIReaderWriter::generateEHFrameHeader( - const DWARFDebugFrame &OldEHFrame, const DWARFDebugFrame &NewEHFrame, - uint64_t EHFrameHeaderAddress, - std::vector &FailedAddresses) const { +std::vector +CFIReaderWriter::generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame, + const DWARFDebugFrame &NewEHFrame, + uint64_t EHFrameHeaderAddress) const { // Common PC -> FDE map to be written into .eh_frame_hdr. std::map PCToFDE; - // Presort array for binary search. - llvm::sort(FailedAddresses); - // Initialize PCToFDE using NewEHFrame. for (dwarf::FrameEntry &Entry : NewEHFrame.entries()) { const dwarf::FDE *FDE = dyn_cast(&Entry); @@ -690,13 +686,7 @@ std::vector CFIReaderWriter::generateEHFrameHeader( continue; // Add the address to the map unless we failed to write it. - if (!std::binary_search(FailedAddresses.begin(), FailedAddresses.end(), - FuncAddress)) { - LLVM_DEBUG(dbgs() << "BOLT-DEBUG: FDE for function at 0x" - << Twine::utohexstr(FuncAddress) << " is at 0x" - << Twine::utohexstr(FDEAddress) << '\n'); - PCToFDE[FuncAddress] = FDEAddress; - } + PCToFDE[FuncAddress] = FDEAddress; }; LLVM_DEBUG(dbgs() << "BOLT-DEBUG: new .eh_frame contains " diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index 5a676185227ec1b00112ea847268928d983bcafc..03d3dd75a033683c2e0760751b793784d3f65e2c 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -588,10 +588,18 @@ Error CheckLargeFunctions::runOnFunctions(BinaryContext &BC) { uint64_t HotSize, ColdSize; std::tie(HotSize, ColdSize) = BC.calculateEmittedSize(BF, /*FixBranches=*/false); - if (HotSize > BF.getMaxSize()) { + uint64_t MainFragmentSize = HotSize; + if (BF.hasIslandsInfo()) { + MainFragmentSize += + offsetToAlignment(BF.getAddress() + MainFragmentSize, + Align(BF.getConstantIslandAlignment())); + MainFragmentSize += BF.estimateConstantIslandSize(); + } + if (MainFragmentSize > BF.getMaxSize()) { if (opts::PrintLargeFunctions) - BC.outs() << "BOLT-INFO: " << BF << " size exceeds allocated space by " - << (HotSize - BF.getMaxSize()) << " bytes\n"; + BC.outs() << "BOLT-INFO: " << BF << " size of " << MainFragmentSize + << " bytes exceeds allocated space by " + << (MainFragmentSize - BF.getMaxSize()) << " bytes\n"; BF.setSimple(false); } }; @@ -1549,10 +1557,48 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) { "BOLT-INFO: inference found an exact match for %.2f%% of basic blocks" " (%zu out of %zu stale) responsible for %.2f%% samples" " (%zu out of %zu stale)\n", - 100.0 * BC.Stats.NumMatchedBlocks / BC.Stats.NumStaleBlocks, - BC.Stats.NumMatchedBlocks, BC.Stats.NumStaleBlocks, - 100.0 * BC.Stats.MatchedSampleCount / BC.Stats.StaleSampleCount, - BC.Stats.MatchedSampleCount, BC.Stats.StaleSampleCount); + 100.0 * BC.Stats.NumExactMatchedBlocks / BC.Stats.NumStaleBlocks, + BC.Stats.NumExactMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.ExactMatchedSampleCount / BC.Stats.StaleSampleCount, + BC.Stats.ExactMatchedSampleCount, BC.Stats.StaleSampleCount); + BC.outs() << format( + "BOLT-INFO: inference found an exact pseudo probe match for %.2f%% of " + "basic blocks (%zu out of %zu stale) responsible for %.2f%% samples" + " (%zu out of %zu stale)\n", + 100.0 * BC.Stats.NumPseudoProbeExactMatchedBlocks / + BC.Stats.NumStaleBlocks, + BC.Stats.NumPseudoProbeExactMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.PseudoProbeExactMatchedSampleCount / + BC.Stats.StaleSampleCount, + BC.Stats.PseudoProbeExactMatchedSampleCount, BC.Stats.StaleSampleCount); + BC.outs() << format( + "BOLT-INFO: inference found a loose pseudo probe match for %.2f%% of " + "basic blocks (%zu out of %zu stale) responsible for %.2f%% samples" + " (%zu out of %zu stale)\n", + 100.0 * BC.Stats.NumPseudoProbeLooseMatchedBlocks / + BC.Stats.NumStaleBlocks, + BC.Stats.NumPseudoProbeLooseMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.PseudoProbeLooseMatchedSampleCount / + BC.Stats.StaleSampleCount, + BC.Stats.PseudoProbeLooseMatchedSampleCount, BC.Stats.StaleSampleCount); + BC.outs() << format( + "BOLT-INFO: inference found a call match for %.2f%% of basic " + "blocks" + " (%zu out of %zu stale) responsible for %.2f%% samples" + " (%zu out of %zu stale)\n", + 100.0 * BC.Stats.NumCallMatchedBlocks / BC.Stats.NumStaleBlocks, + BC.Stats.NumCallMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.CallMatchedSampleCount / BC.Stats.StaleSampleCount, + BC.Stats.CallMatchedSampleCount, BC.Stats.StaleSampleCount); + BC.outs() << format( + "BOLT-INFO: inference found a loose match for %.2f%% of basic " + "blocks" + " (%zu out of %zu stale) responsible for %.2f%% samples" + " (%zu out of %zu stale)\n", + 100.0 * BC.Stats.NumLooseMatchedBlocks / BC.Stats.NumStaleBlocks, + BC.Stats.NumLooseMatchedBlocks, BC.Stats.NumStaleBlocks, + 100.0 * BC.Stats.LooseMatchedSampleCount / BC.Stats.StaleSampleCount, + BC.Stats.LooseMatchedSampleCount, BC.Stats.StaleSampleCount); } if (const uint64_t NumUnusedObjects = BC.getNumUnusedProfiledObjects()) { diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp index 8bf0359477c6584dd93f46a4bc0ddf5191275c93..b386b2756a2b8731fe721e9bf6afdb71083db6a1 100644 --- a/bolt/lib/Passes/VeneerElimination.cpp +++ b/bolt/lib/Passes/VeneerElimination.cpp @@ -29,30 +29,47 @@ static llvm::cl::opt namespace llvm { namespace bolt { +static bool isPossibleVeneer(const BinaryFunction &BF) { + return BF.isAArch64Veneer() || BF.getOneName().starts_with("__AArch64"); +} + Error VeneerElimination::runOnFunctions(BinaryContext &BC) { if (!opts::EliminateVeneers || !BC.isAArch64()) return Error::success(); - std::map &BFs = BC.getBinaryFunctions(); std::unordered_map VeneerDestinations; - uint64_t VeneersCount = 0; - for (auto &It : BFs) { - BinaryFunction &VeneerFunction = It.second; - if (!VeneerFunction.isAArch64Veneer()) + uint64_t NumEliminatedVeneers = 0; + for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) { + if (!isPossibleVeneer(BF)) continue; - VeneersCount++; - VeneerFunction.setPseudo(true); - MCInst &FirstInstruction = *(VeneerFunction.begin()->begin()); - const MCSymbol *VeneerTargetSymbol = - BC.MIB->getTargetSymbol(FirstInstruction, 1); - assert(VeneerTargetSymbol && "Expecting target symbol for instruction"); - for (const MCSymbol *Symbol : VeneerFunction.getSymbols()) + if (BF.isIgnored()) + continue; + + const MCSymbol *VeneerTargetSymbol = 0; + uint64_t TargetAddress; + if (BC.MIB->matchAbsLongVeneer(BF, TargetAddress)) { + if (BinaryFunction *TargetBF = + BC.getBinaryFunctionAtAddress(TargetAddress)) + VeneerTargetSymbol = TargetBF->getSymbol(); + } else { + MCInst &FirstInstruction = *(BF.begin()->begin()); + if (BC.MIB->hasAnnotation(FirstInstruction, "AArch64Veneer")) + VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction, 1); + } + + if (!VeneerTargetSymbol) + continue; + + for (const MCSymbol *Symbol : BF.getSymbols()) VeneerDestinations[Symbol] = VeneerTargetSymbol; + + NumEliminatedVeneers++; + BF.setPseudo(true); } BC.outs() << "BOLT-INFO: number of removed linker-inserted veneers: " - << VeneersCount << "\n"; + << NumEliminatedVeneers << '\n'; // Handle veneers to veneers in case they occur for (auto &Entry : VeneerDestinations) { @@ -65,9 +82,8 @@ Error VeneerElimination::runOnFunctions(BinaryContext &BC) { } uint64_t VeneerCallers = 0; - for (auto &It : BFs) { - BinaryFunction &Function = It.second; - for (BinaryBasicBlock &BB : Function) { + for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) { + for (BinaryBasicBlock &BB : BF) { for (MCInst &Instr : BB) { if (!BC.MIB->isCall(Instr) || BC.MIB->isIndirectCall(Instr)) continue; diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index cd6e96f7e2cf47f14a7a2900a9cb8abf24498934..b66a3f478f1a7b0941851eff16a181c1ff85b14b 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -29,6 +29,7 @@ #include "bolt/Profile/YAMLProfileReader.h" #include "llvm/ADT/Bitfields.h" #include "llvm/ADT/Hashing.h" +#include "llvm/MC/MCPseudoProbe.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Timer.h" #include "llvm/Support/xxhash.h" @@ -116,6 +117,11 @@ cl::opt StaleMatchingCostJumpUnknownFTInc( "The cost of increasing an unknown fall-through jump count by one."), cl::init(3), cl::ReallyHidden, cl::cat(BoltOptCategory)); +cl::opt StaleMatchingWithPseudoProbes( + "stale-matching-with-pseudo-probes", + cl::desc("Turns on stale matching with block pseudo probes."), + cl::init(false), cl::ReallyHidden, cl::cat(BoltOptCategory)); + } // namespace opts namespace llvm { @@ -208,11 +214,48 @@ public: } } - /// Find the most similar block for a given hash. - const FlowBlock *matchBlock(BlendedBlockHash BlendedHash, - uint64_t CallHash) const { - const FlowBlock *BestBlock = matchWithOpcodes(BlendedHash); - return BestBlock ? BestBlock : matchWithCalls(BlendedHash, CallHash); + /// Creates a mapping from a pseudo probe to a flow block. + void mapProbeToBB(const MCDecodedPseudoProbe *Probe, FlowBlock *Block) { + BBPseudoProbeToBlock[Probe] = Block; + } + + enum MatchMethod : char { + MATCH_EXACT = 0, + MATCH_PROBE_EXACT, + MATCH_PROBE_LOOSE, + MATCH_OPCODE, + MATCH_CALL, + NO_MATCH + }; + + /// Find the most similar flow block for a profile block given blended hash. + std::pair + matchBlockStrict(BlendedBlockHash BlendedHash) { + const auto &[Block, ExactHash] = matchWithOpcodes(BlendedHash); + if (Block && ExactHash) + return {Block, MATCH_EXACT}; + return {nullptr, NO_MATCH}; + } + + /// Find the most similar flow block for a profile block given pseudo probes. + std::pair matchBlockProbe( + const ArrayRef PseudoProbes, + const YAMLProfileReader::InlineTreeNodeMapTy &InlineTreeNodeMap) { + const auto &[ProbeBlock, ExactProbe] = + matchWithPseudoProbes(PseudoProbes, InlineTreeNodeMap); + if (ProbeBlock) + return {ProbeBlock, ExactProbe ? MATCH_PROBE_EXACT : MATCH_PROBE_LOOSE}; + return {nullptr, NO_MATCH}; + } + + /// Find the most similar flow block for a profile block given its hashes. + std::pair + matchBlockLoose(BlendedBlockHash BlendedHash, uint64_t CallHash) { + if (const FlowBlock *CallBlock = matchWithCalls(BlendedHash, CallHash)) + return {CallBlock, MATCH_CALL}; + if (const FlowBlock *OpcodeBlock = matchWithOpcodes(BlendedHash).first) + return {OpcodeBlock, MATCH_OPCODE}; + return {nullptr, NO_MATCH}; } /// Returns true if the two basic blocks (in the binary and in the profile) @@ -227,22 +270,26 @@ private: using HashBlockPairType = std::pair; std::unordered_map> OpHashToBlocks; std::unordered_map> CallHashToBlocks; + DenseMap BBPseudoProbeToBlock; // Uses OpcodeHash to find the most similar block for a given hash. - const FlowBlock *matchWithOpcodes(BlendedBlockHash BlendedHash) const { + std::pair + matchWithOpcodes(BlendedBlockHash BlendedHash) const { auto BlockIt = OpHashToBlocks.find(BlendedHash.OpcodeHash); if (BlockIt == OpHashToBlocks.end()) - return nullptr; + return {nullptr, false}; FlowBlock *BestBlock = nullptr; uint64_t BestDist = std::numeric_limits::max(); + BlendedBlockHash BestHash; for (const auto &[Hash, Block] : BlockIt->second) { uint64_t Dist = Hash.distance(BlendedHash); if (BestBlock == nullptr || Dist < BestDist) { BestDist = Dist; BestBlock = Block; + BestHash = Hash; } } - return BestBlock; + return {BestBlock, isHighConfidenceMatch(BestHash, BlendedHash)}; } // Uses CallHash to find the most similar block for a given hash. @@ -266,6 +313,73 @@ private: } return BestBlock; } + + /// Matches a profile block with a binary block based on pseudo probes. + /// Returns the best matching block (or nullptr) and whether the match is + /// unambiguous. + std::pair matchWithPseudoProbes( + const ArrayRef BlockPseudoProbes, + const YAMLProfileReader::InlineTreeNodeMapTy &InlineTreeNodeMap) const { + + if (!opts::StaleMatchingWithPseudoProbes) + return {nullptr, false}; + + DenseMap FlowBlockMatchCount; + + auto matchProfileProbeToBlock = [&](uint32_t NodeId, + uint64_t ProbeId) -> const FlowBlock * { + const MCDecodedPseudoProbeInlineTree *BinaryNode = + InlineTreeNodeMap.getInlineTreeNode(NodeId); + if (!BinaryNode) + return nullptr; + const MCDecodedPseudoProbe Dummy(0, ProbeId, PseudoProbeType::Block, 0, 0, + nullptr); + ArrayRef BinaryProbes = BinaryNode->getProbes(); + auto BinaryProbeIt = llvm::lower_bound( + BinaryProbes, Dummy, [](const auto &LHS, const auto &RHS) { + return LHS.getIndex() < RHS.getIndex(); + }); + if (BinaryProbeIt == BinaryNode->getProbes().end() || + BinaryProbeIt->getIndex() != ProbeId) + return nullptr; + auto It = BBPseudoProbeToBlock.find(&*BinaryProbeIt); + if (It == BBPseudoProbeToBlock.end()) + return nullptr; + return It->second; + }; + + auto matchPseudoProbeInfo = [&](const yaml::bolt::PseudoProbeInfo + &ProfileProbe, + uint32_t NodeId) { + for (uint64_t Index = 0; Index < 64; ++Index) + if (ProfileProbe.BlockMask & 1ull << Index) + ++FlowBlockMatchCount[matchProfileProbeToBlock(NodeId, Index + 1)]; + for (const auto &ProfileProbes : + {ProfileProbe.BlockProbes, ProfileProbe.IndCallProbes, + ProfileProbe.CallProbes}) + for (uint64_t ProfileProbe : ProfileProbes) + ++FlowBlockMatchCount[matchProfileProbeToBlock(NodeId, ProfileProbe)]; + }; + + for (const yaml::bolt::PseudoProbeInfo &ProfileProbe : BlockPseudoProbes) { + if (!ProfileProbe.InlineTreeNodes.empty()) + for (uint32_t ProfileInlineTreeNode : ProfileProbe.InlineTreeNodes) + matchPseudoProbeInfo(ProfileProbe, ProfileInlineTreeNode); + else + matchPseudoProbeInfo(ProfileProbe, ProfileProbe.InlineTreeIndex); + } + uint32_t BestMatchCount = 0; + uint32_t TotalMatchCount = 0; + const FlowBlock *BestMatchBlock = nullptr; + for (const auto &[FlowBlock, Count] : FlowBlockMatchCount) { + TotalMatchCount += Count; + if (Count < BestMatchCount || (Count == BestMatchCount && BestMatchBlock)) + continue; + BestMatchBlock = FlowBlock; + BestMatchCount = Count; + } + return {BestMatchBlock, BestMatchCount == TotalMatchCount}; + } }; void BinaryFunction::computeBlockHashes(HashFunction HashFunction) const { @@ -442,17 +556,18 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) { /// is to extract as much information from the stale profile as possible. Here /// we assume that each basic block is specified via a hash value computed from /// its content and the hashes of the unchanged basic blocks stay the same -/// across different revisions of the binary. +/// across different revisions of the binary. Blocks may also have pseudo probe +/// information in the profile and the binary which is used for matching. /// Whenever there is a count in the profile with the hash corresponding to one /// of the basic blocks in the binary, the count is "matched" to the block. /// Similarly, if both the source and the target of a count in the profile are /// matched to a jump in the binary, the count is recorded in CFG. -size_t -matchWeightsByHashes(BinaryContext &BC, - const BinaryFunction::BasicBlockOrderType &BlockOrder, - const yaml::bolt::BinaryFunctionProfile &YamlBF, - FlowFunction &Func, HashFunction HashFunction, - YAMLProfileReader::ProfileLookupMap &IdToYamlBF) { +size_t matchWeights( + BinaryContext &BC, const BinaryFunction::BasicBlockOrderType &BlockOrder, + const yaml::bolt::BinaryFunctionProfile &YamlBF, FlowFunction &Func, + HashFunction HashFunction, YAMLProfileReader::ProfileLookupMap &IdToYamlBF, + const BinaryFunction &BF, + const ArrayRef ProbeMatchSpecs) { assert(Func.Blocks.size() == BlockOrder.size() + 2); @@ -482,16 +597,67 @@ matchWeightsByHashes(BinaryContext &BC, << Twine::utohexstr(BB->getHash()) << "\n"); } StaleMatcher Matcher; + // Collects function pseudo probes for use in the StaleMatcher. + if (opts::StaleMatchingWithPseudoProbes) { + const MCPseudoProbeDecoder *Decoder = BC.getPseudoProbeDecoder(); + assert(Decoder && + "If pseudo probes are in use, pseudo probe decoder should exist"); + const AddressProbesMap &ProbeMap = Decoder->getAddress2ProbesMap(); + const uint64_t FuncAddr = BF.getAddress(); + for (const MCDecodedPseudoProbe &Probe : + ProbeMap.find(FuncAddr, FuncAddr + BF.getSize())) + if (const BinaryBasicBlock *BB = + BF.getBasicBlockContainingOffset(Probe.getAddress() - FuncAddr)) + Matcher.mapProbeToBB(&Probe, Blocks[BB->getIndex()]); + } Matcher.init(Blocks, BlendedHashes, CallHashes); - // Index in yaml profile => corresponding (matched) block - DenseMap MatchedBlocks; - // Match blocks from the profile to the blocks in CFG + using FlowBlockTy = + std::pair; + using ProfileBlockMatchMap = DenseMap; + // Binary profile => block index => matched block + its block profile + DenseMap + MatchedBlocks; + + // Map of FlowBlock and matching method. + DenseMap MatchedFlowBlocks; + + auto addMatchedBlock = + [&](std::pair BlockMethod, + const yaml::bolt::BinaryFunctionProfile &YamlBP, + const yaml::bolt::BinaryBasicBlockProfile &YamlBB) { + const auto &[MatchedBlock, Method] = BlockMethod; + if (!MatchedBlock) + return; + // Don't override earlier matches + if (MatchedFlowBlocks.contains(MatchedBlock)) + return; + MatchedFlowBlocks.try_emplace(MatchedBlock, Method); + MatchedBlocks[&YamlBP][YamlBB.Index] = {MatchedBlock, &YamlBB}; + }; + + // Match blocks from the profile to the blocks in CFG by strict hash. + for (const yaml::bolt::BinaryBasicBlockProfile &YamlBB : YamlBF.Blocks) { + // Update matching stats. + ++BC.Stats.NumStaleBlocks; + BC.Stats.StaleSampleCount += YamlBB.ExecCount; + + assert(YamlBB.Hash != 0 && "empty hash of BinaryBasicBlockProfile"); + BlendedBlockHash YamlHash(YamlBB.Hash); + addMatchedBlock(Matcher.matchBlockStrict(YamlHash), YamlBF, YamlBB); + } + // Match blocks from the profile to the blocks in CFG by pseudo probes. + for (const auto &[InlineNodeMap, YamlBP] : ProbeMatchSpecs) { + for (const yaml::bolt::BinaryBasicBlockProfile &BB : YamlBP.get().Blocks) + if (!BB.PseudoProbes.empty()) + addMatchedBlock(Matcher.matchBlockProbe(BB.PseudoProbes, InlineNodeMap), + YamlBP, BB); + } + // Match blocks from the profile to the blocks in CFG with loose methods. for (const yaml::bolt::BinaryBasicBlockProfile &YamlBB : YamlBF.Blocks) { assert(YamlBB.Hash != 0 && "empty hash of BinaryBasicBlockProfile"); BlendedBlockHash YamlHash(YamlBB.Hash); - const FlowBlock *MatchedBlock = nullptr; std::string CallHashStr = hashBlockCalls(IdToYamlBF, YamlBB); uint64_t CallHash = 0; if (!CallHashStr.empty()) { @@ -502,76 +668,104 @@ matchWeightsByHashes(BinaryContext &BC, else llvm_unreachable("Unhandled HashFunction"); } - MatchedBlock = Matcher.matchBlock(YamlHash, CallHash); - if (MatchedBlock == nullptr && YamlBB.Index == 0) + auto [MatchedBlock, Method] = Matcher.matchBlockLoose(YamlHash, CallHash); + if (MatchedBlock == nullptr && YamlBB.Index == 0) { MatchedBlock = Blocks[0]; - if (MatchedBlock != nullptr) { - const BinaryBasicBlock *BB = BlockOrder[MatchedBlock->Index - 1]; - MatchedBlocks[YamlBB.Index] = MatchedBlock; + // Report as loose match + Method = StaleMatcher::MATCH_OPCODE; + } + if (!MatchedBlock) { + LLVM_DEBUG(dbgs() << "Couldn't match yaml block (bid = " << YamlBB.Index + << ")" << " with hash " << Twine::utohexstr(YamlBB.Hash) + << "\n"); + continue; + } + addMatchedBlock({MatchedBlock, Method}, YamlBF, YamlBB); + } + + // Match jumps from the profile to the jumps from CFG + std::vector OutWeight(Func.Blocks.size(), 0); + std::vector InWeight(Func.Blocks.size(), 0); + + for (const auto &[YamlBF, MatchMap] : MatchedBlocks) { + for (const auto &[YamlBBIdx, FlowBlockProfile] : MatchMap) { + const auto &[MatchedBlock, YamlBB] = FlowBlockProfile; + StaleMatcher::MatchMethod Method = MatchedFlowBlocks.lookup(MatchedBlock); BlendedBlockHash BinHash = BlendedHashes[MatchedBlock->Index - 1]; - LLVM_DEBUG(dbgs() << "Matched yaml block (bid = " << YamlBB.Index << ")" - << " with hash " << Twine::utohexstr(YamlBB.Hash) + LLVM_DEBUG(dbgs() << "Matched yaml block (bid = " << YamlBBIdx << ")" + << " with hash " << Twine::utohexstr(YamlBB->Hash) << " to BB (index = " << MatchedBlock->Index - 1 << ")" << " with hash " << Twine::utohexstr(BinHash.combine()) << "\n"); + (void)BinHash; + uint64_t ExecCount = YamlBB->ExecCount; // Update matching stats accounting for the matched block. - if (Matcher.isHighConfidenceMatch(BinHash, YamlHash)) { - ++BC.Stats.NumMatchedBlocks; - BC.Stats.MatchedSampleCount += YamlBB.ExecCount; + switch (Method) { + case StaleMatcher::MATCH_EXACT: + ++BC.Stats.NumExactMatchedBlocks; + BC.Stats.ExactMatchedSampleCount += ExecCount; LLVM_DEBUG(dbgs() << " exact match\n"); - } else { + break; + case StaleMatcher::MATCH_PROBE_EXACT: + ++BC.Stats.NumPseudoProbeExactMatchedBlocks; + BC.Stats.PseudoProbeExactMatchedSampleCount += ExecCount; + LLVM_DEBUG(dbgs() << " exact pseudo probe match\n"); + break; + case StaleMatcher::MATCH_PROBE_LOOSE: + ++BC.Stats.NumPseudoProbeLooseMatchedBlocks; + BC.Stats.PseudoProbeLooseMatchedSampleCount += ExecCount; + LLVM_DEBUG(dbgs() << " loose pseudo probe match\n"); + break; + case StaleMatcher::MATCH_CALL: + ++BC.Stats.NumCallMatchedBlocks; + BC.Stats.CallMatchedSampleCount += ExecCount; + LLVM_DEBUG(dbgs() << " call match\n"); + break; + case StaleMatcher::MATCH_OPCODE: + ++BC.Stats.NumLooseMatchedBlocks; + BC.Stats.LooseMatchedSampleCount += ExecCount; LLVM_DEBUG(dbgs() << " loose match\n"); + break; + case StaleMatcher::NO_MATCH: + LLVM_DEBUG(dbgs() << " no match\n"); } - if (YamlBB.NumInstructions == BB->size()) - ++BC.Stats.NumStaleBlocksWithEqualIcount; - } else { - LLVM_DEBUG( - dbgs() << "Couldn't match yaml block (bid = " << YamlBB.Index << ")" - << " with hash " << Twine::utohexstr(YamlBB.Hash) << "\n"); } - // Update matching stats. - ++BC.Stats.NumStaleBlocks; - BC.Stats.StaleSampleCount += YamlBB.ExecCount; - } - - // Match jumps from the profile to the jumps from CFG - std::vector OutWeight(Func.Blocks.size(), 0); - std::vector InWeight(Func.Blocks.size(), 0); - for (const yaml::bolt::BinaryBasicBlockProfile &YamlBB : YamlBF.Blocks) { - for (const yaml::bolt::SuccessorInfo &YamlSI : YamlBB.Successors) { - if (YamlSI.Count == 0) - continue; - - // Try to find the jump for a given (src, dst) pair from the profile and - // assign the jump weight based on the profile count - const uint64_t SrcIndex = YamlBB.Index; - const uint64_t DstIndex = YamlSI.Index; - - const FlowBlock *MatchedSrcBlock = MatchedBlocks.lookup(SrcIndex); - const FlowBlock *MatchedDstBlock = MatchedBlocks.lookup(DstIndex); - - if (MatchedSrcBlock != nullptr && MatchedDstBlock != nullptr) { - // Find a jump between the two blocks - FlowJump *Jump = nullptr; - for (FlowJump *SuccJump : MatchedSrcBlock->SuccJumps) { - if (SuccJump->Target == MatchedDstBlock->Index) { - Jump = SuccJump; - break; + for (const yaml::bolt::BinaryBasicBlockProfile &YamlBB : YamlBF->Blocks) { + for (const yaml::bolt::SuccessorInfo &YamlSI : YamlBB.Successors) { + if (YamlSI.Count == 0) + continue; + + // Try to find the jump for a given (src, dst) pair from the profile and + // assign the jump weight based on the profile count + const uint64_t SrcIndex = YamlBB.Index; + const uint64_t DstIndex = YamlSI.Index; + + const FlowBlock *MatchedSrcBlock = MatchMap.lookup(SrcIndex).first; + const FlowBlock *MatchedDstBlock = MatchMap.lookup(DstIndex).first; + + if (MatchedSrcBlock != nullptr && MatchedDstBlock != nullptr) { + // Find a jump between the two blocks + FlowJump *Jump = nullptr; + for (FlowJump *SuccJump : MatchedSrcBlock->SuccJumps) { + if (SuccJump->Target == MatchedDstBlock->Index) { + Jump = SuccJump; + break; + } + } + // Assign the weight, if the corresponding jump is found + if (Jump != nullptr) { + Jump->Weight = YamlSI.Count; + Jump->HasUnknownWeight = false; } } - // Assign the weight, if the corresponding jump is found - if (Jump != nullptr) { - Jump->Weight = YamlSI.Count; - Jump->HasUnknownWeight = false; - } + // Assign the weight for the src block, if it is found + if (MatchedSrcBlock != nullptr) + OutWeight[MatchedSrcBlock->Index] += YamlSI.Count; + // Assign the weight for the dst block, if it is found + if (MatchedDstBlock != nullptr) + InWeight[MatchedDstBlock->Index] += YamlSI.Count; } - // Assign the weight for the src block, if it is found - if (MatchedSrcBlock != nullptr) - OutWeight[MatchedSrcBlock->Index] += YamlSI.Count; - // Assign the weight for the dst block, if it is found - if (MatchedDstBlock != nullptr) - InWeight[MatchedDstBlock->Index] += YamlSI.Count; } } @@ -585,7 +779,7 @@ matchWeightsByHashes(BinaryContext &BC, Block.Weight = std::max(OutWeight[Block.Index], InWeight[Block.Index]); } - return MatchedBlocks.size(); + return MatchedBlocks[&YamlBF].size(); } /// The function finds all blocks that are (i) reachable from the Entry block @@ -803,7 +997,8 @@ void assignProfile(BinaryFunction &BF, } bool YAMLProfileReader::inferStaleProfile( - BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) { + BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF, + const ArrayRef ProbeMatchSpecs) { NamedRegionTimer T("inferStaleProfile", "stale profile inference", "rewrite", "Rewrite passes", opts::TimeRewrite); @@ -827,8 +1022,8 @@ bool YAMLProfileReader::inferStaleProfile( // Match as many block/jump counts from the stale profile as possible size_t MatchedBlocks = - matchWeightsByHashes(BF.getBinaryContext(), BlockOrder, YamlBF, Func, - YamlBP.Header.HashFunction, IdToYamLBF); + matchWeights(BF.getBinaryContext(), BlockOrder, YamlBF, Func, + YamlBP.Header.HashFunction, IdToYamLBF, BF, ProbeMatchSpecs); // Adjust the flow function by marking unreachable blocks Unlikely so that // they don't get any counts assigned. diff --git a/bolt/lib/Profile/YAMLProfileReader.cpp b/bolt/lib/Profile/YAMLProfileReader.cpp index a5dc8492b590033e720dd90db1a3e558980c3c24..e3872b373f417888ca9d43b2571c25b0be16bd7c 100644 --- a/bolt/lib/Profile/YAMLProfileReader.cpp +++ b/bolt/lib/Profile/YAMLProfileReader.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/edit_distance.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/MC/MCPseudoProbe.h" #include "llvm/Support/CommandLine.h" using namespace llvm; @@ -49,6 +50,8 @@ llvm::cl::opt llvm::cl::opt ProfileUseDFS("profile-use-dfs", cl::desc("use DFS order for YAML profile"), cl::Hidden, cl::cat(BoltOptCategory)); + +extern llvm::cl::opt StaleMatchingWithPseudoProbes; } // namespace opts namespace llvm { @@ -349,8 +352,13 @@ bool YAMLProfileReader::parseFunctionProfile( if (YamlBF.NumBasicBlocks != BF.size()) ++BC.Stats.NumStaleFuncsWithEqualBlockCount; - if (opts::InferStaleProfile && inferStaleProfile(BF, YamlBF)) - ProfileMatched = true; + if (!opts::InferStaleProfile) + return false; + ArrayRef ProbeMatchSpecs; + auto BFIt = BFToProbeMatchSpecs.find(&BF); + if (BFIt != BFToProbeMatchSpecs.end()) + ProbeMatchSpecs = BFIt->second; + ProfileMatched = inferStaleProfile(BF, YamlBF, ProbeMatchSpecs); } if (ProfileMatched) BF.markProfiled(YamlBP.Header.Flags); @@ -585,6 +593,101 @@ size_t YAMLProfileReader::matchWithCallGraph(BinaryContext &BC) { return MatchedWithCallGraph; } +size_t YAMLProfileReader::InlineTreeNodeMapTy::matchInlineTrees( + const MCPseudoProbeDecoder &Decoder, + const std::vector &DecodedInlineTree, + const MCDecodedPseudoProbeInlineTree *Root) { + // Match inline tree nodes by GUID, checksum, parent, and call site. + for (const auto &[InlineTreeNodeId, InlineTreeNode] : + llvm::enumerate(DecodedInlineTree)) { + uint64_t GUID = InlineTreeNode.GUID; + uint64_t Hash = InlineTreeNode.Hash; + uint32_t ParentId = InlineTreeNode.ParentIndexDelta; + uint32_t CallSiteProbe = InlineTreeNode.CallSiteProbe; + const MCDecodedPseudoProbeInlineTree *Cur = nullptr; + if (!InlineTreeNodeId) { + Cur = Root; + } else if (const MCDecodedPseudoProbeInlineTree *Parent = + getInlineTreeNode(ParentId)) { + for (const MCDecodedPseudoProbeInlineTree &Child : + Parent->getChildren()) { + if (Child.Guid == GUID) { + if (std::get<1>(Child.getInlineSite()) == CallSiteProbe) + Cur = &Child; + break; + } + } + } + // Don't match nodes if the profile is stale (mismatching binary FuncHash + // and YAML Hash) + if (Cur && Decoder.getFuncDescForGUID(Cur->Guid)->FuncHash == Hash) + mapInlineTreeNode(InlineTreeNodeId, Cur); + } + return Map.size(); +} + +// Decode index deltas and indirection through \p YamlPD. Return modified copy +// of \p YamlInlineTree with populated decoded fields (GUID, Hash, ParentIndex). +static std::vector +decodeYamlInlineTree(const yaml::bolt::ProfilePseudoProbeDesc &YamlPD, + std::vector YamlInlineTree) { + uint32_t ParentId = 0; + uint32_t PrevGUIDIdx = 0; + for (yaml::bolt::InlineTreeNode &InlineTreeNode : YamlInlineTree) { + uint32_t GUIDIdx = InlineTreeNode.GUIDIndex; + if (GUIDIdx != UINT32_MAX) + PrevGUIDIdx = GUIDIdx; + else + GUIDIdx = PrevGUIDIdx; + uint32_t HashIdx = YamlPD.GUIDHashIdx[GUIDIdx]; + ParentId += InlineTreeNode.ParentIndexDelta; + InlineTreeNode.GUID = YamlPD.GUID[GUIDIdx]; + InlineTreeNode.Hash = YamlPD.Hash[HashIdx]; + InlineTreeNode.ParentIndexDelta = ParentId; + } + return YamlInlineTree; +} + +size_t YAMLProfileReader::matchWithPseudoProbes(BinaryContext &BC) { + if (!opts::StaleMatchingWithPseudoProbes) + return 0; + + const MCPseudoProbeDecoder *Decoder = BC.getPseudoProbeDecoder(); + const yaml::bolt::ProfilePseudoProbeDesc &YamlPD = YamlBP.PseudoProbeDesc; + + // Set existing BF->YamlBF match into ProbeMatchSpecs for (local) probe + // matching. + assert(Decoder && + "If pseudo probes are in use, pseudo probe decoder should exist"); + for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs)) { + // BF is preliminary name-matched function to YamlBF + // MatchedBF is final matched function + BinaryFunction *MatchedBF = YamlProfileToFunction.lookup(YamlBF.Id); + if (!BF) + BF = MatchedBF; + if (!BF) + continue; + uint64_t GUID = BF->getGUID(); + if (!GUID) + continue; + auto It = TopLevelGUIDToInlineTree.find(GUID); + if (It == TopLevelGUIDToInlineTree.end()) + continue; + const MCDecodedPseudoProbeInlineTree *Node = It->second; + assert(Node && "Malformed TopLevelGUIDToInlineTree"); + auto &MatchSpecs = BFToProbeMatchSpecs[BF]; + auto &InlineTreeMap = + MatchSpecs.emplace_back(InlineTreeNodeMapTy(), YamlBF).first; + std::vector ProfileInlineTree = + decodeYamlInlineTree(YamlPD, YamlBF.InlineTree); + // Erase unsuccessful match + if (!InlineTreeMap.matchInlineTrees(*Decoder, ProfileInlineTree, Node)) + MatchSpecs.pop_back(); + } + + return 0; +} + size_t YAMLProfileReader::matchWithNameSimilarity(BinaryContext &BC) { if (opts::NameSimilarityFunctionMatchingThreshold == 0) return 0; @@ -716,6 +819,15 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) { } } + if (opts::StaleMatchingWithPseudoProbes) { + const MCPseudoProbeDecoder *Decoder = BC.getPseudoProbeDecoder(); + assert(Decoder && + "If pseudo probes are in use, pseudo probe decoder should exist"); + for (const MCDecodedPseudoProbeInlineTree &TopLev : + Decoder->getDummyInlineRoot().getChildren()) + TopLevelGUIDToInlineTree[TopLev.Guid] = &TopLev; + } + // Map profiled function ids to names. for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) IdToYamLBF[YamlBF.Id] = &YamlBF; @@ -725,6 +837,8 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) { const size_t MatchedWithLTOCommonName = matchWithLTOCommonName(); const size_t MatchedWithCallGraph = matchWithCallGraph(BC); const size_t MatchedWithNameSimilarity = matchWithNameSimilarity(BC); + [[maybe_unused]] const size_t MatchedWithPseudoProbes = + matchWithPseudoProbes(BC); for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs)) if (!YamlBF.Used && BF && !ProfiledFunctions.count(BF)) diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index 4437be423ff431951e54f1a6ffc14fb4b6f0d8f0..e394858163560b4b9d6c6090d8578c1e4c7d715e 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -203,7 +203,7 @@ YAMLProfileWriter::convertBFInlineTree(const MCPseudoProbeDecoder &Decoder, else PrevGUIDIdx = GUIDIdx; YamlInlineTree.emplace_back(yaml::bolt::InlineTreeNode{ - Node.ParentId - PrevParent, Node.InlineSite, GUIDIdx}); + Node.ParentId - PrevParent, Node.InlineSite, GUIDIdx, 0, 0}); PrevParent = Node.ParentId; } return {YamlInlineTree, InlineTreeNodeId}; diff --git a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp index 09aa4fbb66bd42872a7159570ac354c5d08edd7d..9d6e914624a33f2265ddd6a9882a47aa1e4bfe3f 100644 --- a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp +++ b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp @@ -51,6 +51,7 @@ static cl::opt PrintPseudoProbes( cl::Hidden, cl::cat(BoltCategory)); extern cl::opt ProfileWritePseudoProbes; +extern cl::opt StaleMatchingWithPseudoProbes; } // namespace opts namespace { @@ -92,14 +93,14 @@ public: }; Error PseudoProbeRewriter::preCFGInitializer() { - if (opts::ProfileWritePseudoProbes) - parsePseudoProbe(true); + if (opts::ProfileWritePseudoProbes || opts::StaleMatchingWithPseudoProbes) + parsePseudoProbe(opts::ProfileWritePseudoProbes); return Error::success(); } Error PseudoProbeRewriter::postEmitFinalizer() { - if (!opts::ProfileWritePseudoProbes) + if (!opts::StaleMatchingWithPseudoProbes) parsePseudoProbe(); updatePseudoProbes(); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index a4c50cbc3e2bbf8925e59940dd7f6b9e41206098..7059a3dd231099beae7cfce4692030adae4b7ee4 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -3807,7 +3807,6 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { if (!Function.isEmitted()) continue; - bool TooLarge = false; ErrorOr FuncSection = Function.getCodeSection(); assert(FuncSection && "cannot find section for function"); FuncSection->setOutputAddress(Function.getAddress()); @@ -3818,11 +3817,8 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { MapSection(*FuncSection, Function.getAddress()); Function.setImageAddress(FuncSection->getAllocAddress()); Function.setImageSize(FuncSection->getOutputSize()); - if (Function.getImageSize() > Function.getMaxSize()) { - assert(!BC->isX86() && "Unexpected large function."); - TooLarge = true; - FailedAddresses.emplace_back(Function.getAddress()); - } + assert(Function.getImageSize() <= Function.getMaxSize() && + "Unexpected large function"); // Map jump tables if updating in-place. if (opts::JumpTables == JTS_BASIC) { @@ -3852,19 +3848,11 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { assert(ColdSection && "cannot find section for cold part"); // Cold fragments are aligned at 16 bytes. NextAvailableAddress = alignTo(NextAvailableAddress, 16); - if (TooLarge) { - // The corresponding FDE will refer to address 0. - FF.setAddress(0); - FF.setImageAddress(0); - FF.setImageSize(0); - FF.setFileOffset(0); - } else { - FF.setAddress(NextAvailableAddress); - FF.setImageAddress(ColdSection->getAllocAddress()); - FF.setImageSize(ColdSection->getOutputSize()); - FF.setFileOffset(getFileOffsetForAddress(NextAvailableAddress)); - ColdSection->setOutputAddress(FF.getAddress()); - } + FF.setAddress(NextAvailableAddress); + FF.setImageAddress(ColdSection->getAllocAddress()); + FF.setImageSize(ColdSection->getOutputSize()); + FF.setFileOffset(getFileOffsetForAddress(NextAvailableAddress)); + ColdSection->setOutputAddress(FF.getAddress()); LLVM_DEBUG( dbgs() << formatv( @@ -3872,9 +3860,6 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { FF.getImageAddress(), FF.getAddress(), FF.getImageSize())); MapSection(*ColdSection, FF.getAddress()); - if (TooLarge) - BC->deregisterSection(*ColdSection); - NextAvailableAddress += FF.getImageSize(); } @@ -3902,6 +3887,43 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { void RewriteInstance::mapAllocatableSections( BOLTLinker::SectionMapper MapSection) { + + if (opts::UseOldText || opts::StrictMode) { + auto tryRewriteSection = [&](BinarySection &OldSection, + BinarySection &NewSection) { + if (OldSection.getSize() < NewSection.getOutputSize()) + return; + + BC->outs() << "BOLT-INFO: rewriting " << OldSection.getName() + << " in-place\n"; + + NewSection.setOutputAddress(OldSection.getAddress()); + NewSection.setOutputFileOffset(OldSection.getInputFileOffset()); + MapSection(NewSection, OldSection.getAddress()); + + // Pad contents with zeros. + NewSection.addPadding(OldSection.getSize() - NewSection.getOutputSize()); + + // Prevent the original section name from appearing in the section header + // table. + OldSection.setAnonymous(true); + }; + + if (EHFrameSection) { + BinarySection *NewEHFrameSection = + getSection(getNewSecPrefix() + getEHFrameSectionName()); + assert(NewEHFrameSection && "New contents expected for .eh_frame"); + tryRewriteSection(*EHFrameSection, *NewEHFrameSection); + } + BinarySection *EHSection = getSection(".gcc_except_table"); + BinarySection *NewEHSection = + getSection(getNewSecPrefix() + ".gcc_except_table"); + if (EHSection) { + assert(NewEHSection && "New contents expected for .gcc_except_table"); + tryRewriteSection(*EHSection, *NewEHSection); + } + } + // Allocate read-only sections first, then writable sections. enum : uint8_t { ST_READONLY, ST_READWRITE }; for (uint8_t SType = ST_READONLY; SType <= ST_READWRITE; ++SType) { @@ -4179,7 +4201,6 @@ void RewriteInstance::rewriteNoteSections() { // New section size. uint64_t Size = 0; bool DataWritten = false; - uint8_t *SectionData = nullptr; // Copy over section contents unless it's one of the sections we overwrite. if (!willOverwriteSection(SectionName)) { Size = Section.sh_size; @@ -4211,12 +4232,7 @@ void RewriteInstance::rewriteNoteSections() { if (BSec->getAllocAddress()) { assert(!DataWritten && "Writing section twice."); (void)DataWritten; - SectionData = BSec->getOutputData(); - - LLVM_DEBUG(dbgs() << "BOLT-DEBUG: " << (Size ? "appending" : "writing") - << " contents to section " << SectionName << '\n'); - OS.write(reinterpret_cast(SectionData), BSec->getOutputSize()); - Size += BSec->getOutputSize(); + Size += BSec->write(OS); } BSec->setOutputFileOffset(NextAvailableOffset); @@ -4247,8 +4263,7 @@ void RewriteInstance::rewriteNoteSections() { << " of size " << Section.getOutputSize() << " at offset 0x" << Twine::utohexstr(Section.getOutputFileOffset()) << '\n'); - OS.write(Section.getOutputContents().data(), Section.getOutputSize()); - NextAvailableOffset += Section.getOutputSize(); + NextAvailableOffset += Section.write(OS); } } @@ -4362,6 +4377,10 @@ RewriteInstance::getOutputSections(ELFObjectFile *File, BinarySection *BinSec = BC->getSectionForSectionRef(SecRef); assert(BinSec && "Matching BinarySection should exist."); + // Exclude anonymous sections. + if (BinSec->isAnonymous()) + continue; + addSection(Section, *BinSec); } @@ -5714,8 +5733,8 @@ void RewriteInstance::rewriteFile() { << Twine::utohexstr(Section.getAllocAddress()) << "\n of size " << Section.getOutputSize() << "\n at offset " << Section.getOutputFileOffset() << '\n'; - OS.pwrite(reinterpret_cast(Section.getOutputData()), - Section.getOutputSize(), Section.getOutputFileOffset()); + OS.seek(Section.getOutputFileOffset()); + Section.write(OS); } for (BinarySection &Section : BC->allocatableSections()) @@ -5806,42 +5825,64 @@ void RewriteInstance::writeEHFrameHeader() { LLVM_DEBUG(dbgs() << "BOLT: writing a new " << getEHFrameHdrSectionName() << '\n'); - NextAvailableAddress = - appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign); + // Try to overwrite the original .eh_frame_hdr if the size permits. + uint64_t EHFrameHdrOutputAddress = 0; + uint64_t EHFrameHdrFileOffset = 0; + std::vector NewEHFrameHdr; + BinarySection *OldEHFrameHdrSection = getSection(getEHFrameHdrSectionName()); + if (OldEHFrameHdrSection) { + NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader( + RelocatedEHFrame, NewEHFrame, OldEHFrameHdrSection->getAddress()); + if (NewEHFrameHdr.size() <= OldEHFrameHdrSection->getSize()) { + BC->outs() << "BOLT-INFO: rewriting " << getEHFrameHdrSectionName() + << " in-place\n"; + EHFrameHdrOutputAddress = OldEHFrameHdrSection->getAddress(); + EHFrameHdrFileOffset = OldEHFrameHdrSection->getInputFileOffset(); + } else { + OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() + + getEHFrameHdrSectionName()); + OldEHFrameHdrSection = nullptr; + } + } + + // If there was not enough space, allocate more memory for .eh_frame_hdr. + if (!OldEHFrameHdrSection) { + NextAvailableAddress = + appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign); - const uint64_t EHFrameHdrOutputAddress = NextAvailableAddress; - const uint64_t EHFrameHdrFileOffset = - getFileOffsetForAddress(NextAvailableAddress); + EHFrameHdrOutputAddress = NextAvailableAddress; + EHFrameHdrFileOffset = getFileOffsetForAddress(NextAvailableAddress); - std::vector NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader( - RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses); + NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader( + RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress); + + NextAvailableAddress += NewEHFrameHdr.size(); + if (!BC->BOLTReserved.empty() && + (NextAvailableAddress > BC->BOLTReserved.end())) { + BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName() + << " into reserved space\n"; + exit(1); + } + + // Create a new entry in the section header table. + const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true, + /*IsText=*/false, + /*IsAllocatable=*/true); + BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection( + getNewSecPrefix() + getEHFrameHdrSectionName(), ELF::SHT_PROGBITS, + Flags, nullptr, NewEHFrameHdr.size(), /*Alignment=*/1); + EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset); + EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress); + EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName()); + } Out->os().seek(EHFrameHdrFileOffset); Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size()); - const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true, - /*IsText=*/false, - /*IsAllocatable=*/true); - BinarySection *OldEHFrameHdrSection = getSection(getEHFrameHdrSectionName()); + // Pad the contents if overwriting in-place. if (OldEHFrameHdrSection) - OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() + - getEHFrameHdrSectionName()); - - BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection( - getNewSecPrefix() + getEHFrameHdrSectionName(), ELF::SHT_PROGBITS, Flags, - nullptr, NewEHFrameHdr.size(), /*Alignment=*/1); - EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset); - EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress); - EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName()); - - NextAvailableAddress += EHFrameHdrSec.getOutputSize(); - - if (!BC->BOLTReserved.empty() && - (NextAvailableAddress > BC->BOLTReserved.end())) { - BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName() - << " into reserved space\n"; - exit(1); - } + Out->os().write_zeros(OldEHFrameHdrSection->getSize() - + NewEHFrameHdr.size()); // Merge new .eh_frame with the relocated original so that gdb can locate all // FDEs. diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index f58f7857e28aeb075dd5eaa13c35e1045fa01fc0..7e08e5c81d26ffaa21e6c2dd7d1c11c3f6de1a00 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -15,6 +15,8 @@ #include "MCTargetDesc/AArch64MCExpr.h" #include "MCTargetDesc/AArch64MCTargetDesc.h" #include "Utils/AArch64BaseInfo.h" +#include "bolt/Core/BinaryBasicBlock.h" +#include "bolt/Core/BinaryFunction.h" #include "bolt/Core/MCPlusBuilder.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" @@ -22,6 +24,7 @@ #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -1320,6 +1323,67 @@ public: return 3; } + /// Match the following pattern: + /// + /// LDR x16, .L1 + /// BR x16 + /// L1: + /// .quad Target + /// + /// Populate \p TargetAddress with the Target value on successful match. + bool matchAbsLongVeneer(const BinaryFunction &BF, + uint64_t &TargetAddress) const override { + if (BF.size() != 1 || BF.getMaxSize() < 16) + return false; + + if (!BF.hasConstantIsland()) + return false; + + const BinaryBasicBlock &BB = BF.front(); + if (BB.size() != 2) + return false; + + const MCInst &LDRInst = BB.getInstructionAtIndex(0); + if (LDRInst.getOpcode() != AArch64::LDRXl) + return false; + + if (!LDRInst.getOperand(0).isReg() || + LDRInst.getOperand(0).getReg() != AArch64::X16) + return false; + + const MCSymbol *TargetSym = getTargetSymbol(LDRInst, 1); + if (!TargetSym) + return false; + + const MCInst &BRInst = BB.getInstructionAtIndex(1); + if (BRInst.getOpcode() != AArch64::BR) + return false; + if (!BRInst.getOperand(0).isReg() || + BRInst.getOperand(0).getReg() != AArch64::X16) + return false; + + const BinaryFunction::IslandInfo &IInfo = BF.getIslandInfo(); + if (IInfo.HasDynamicRelocations) + return false; + + auto Iter = IInfo.Offsets.find(8); + if (Iter == IInfo.Offsets.end() || Iter->second != TargetSym) + return false; + + // Extract the absolute value stored inside the island. + StringRef SectionContents = BF.getOriginSection()->getContents(); + StringRef FunctionContents = SectionContents.substr( + BF.getAddress() - BF.getOriginSection()->getAddress(), BF.getMaxSize()); + + const BinaryContext &BC = BF.getBinaryContext(); + DataExtractor DE(FunctionContents, BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + uint64_t Offset = 8; + TargetAddress = DE.getAddress(&Offset); + + return true; + } + bool matchAdrpAddPair(const MCInst &Adrp, const MCInst &Add) const override { if (!isADRP(Adrp) || !isAddXri(Add)) return false; diff --git a/bolt/test/AArch64/veneer-lld-abs.s b/bolt/test/AArch64/veneer-lld-abs.s new file mode 100644 index 0000000000000000000000000000000000000000..d10ff46e2cb01680528485e667da7a58ade886ad --- /dev/null +++ b/bolt/test/AArch64/veneer-lld-abs.s @@ -0,0 +1,51 @@ +## Check that llvm-bolt correctly recognizes long absolute thunks generated +## by LLD. + +# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -fno-PIC -no-pie %t.o -o %t.exe -nostdlib \ +# RUN: -fuse-ld=lld -Wl,-q +# RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=CHECK-INPUT %s +# RUN: llvm-objcopy --remove-section .rela.mytext %t.exe +# RUN: llvm-bolt %t.exe -o %t.bolt --elim-link-veneers=true --lite=0 +# RUN: llvm-objdump -d -j .text %t.bolt | \ +# RUN: FileCheck --check-prefix=CHECK-OUTPUT %s + +.text +.balign 4 +.global foo +.type foo, %function +foo: + adrp x1, foo + ret +.size foo, .-foo + +.section ".mytext", "ax" +.balign 4 + +.global __AArch64AbsLongThunk_foo +.type __AArch64AbsLongThunk_foo, %function +__AArch64AbsLongThunk_foo: + ldr x16, .L1 + br x16 +# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_foo>: +# CHECK-INPUT-NEXT: ldr +# CHECK-INPUT-NEXT: br +.L1: + .quad foo +.size __AArch64AbsLongThunk_foo, .-__AArch64AbsLongThunk_foo + +## Check that the thunk was removed from .text and _start() calls foo() +## directly. + +# CHECK-OUTPUT-NOT: __AArch64AbsLongThunk_foo + +.global _start +.type _start, %function +_start: +# CHECK-INPUT-LABEL: <_start>: +# CHECK-OUTPUT-LABEL: <_start>: + bl __AArch64AbsLongThunk_foo +# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_foo> +# CHECK-OUTPUT-NEXT: bl {{.*}} + ret +.size _start, .-_start diff --git a/bolt/test/X86/match-blocks-with-pseudo-probes-inline.test b/bolt/test/X86/match-blocks-with-pseudo-probes-inline.test new file mode 100644 index 0000000000000000000000000000000000000000..accb4742851ea574e5bafae272b4b4d3622208ac --- /dev/null +++ b/bolt/test/X86/match-blocks-with-pseudo-probes-inline.test @@ -0,0 +1,65 @@ +## Test stale block matching with pseudo probes including inline tree matching. +# RUN: split-file %s %t +# RUN: llvm-bolt \ +# RUN: %S/../../../llvm/test/tools/llvm-profgen/Inputs/inline-cs-pseudoprobe.perfbin \ +# RUN: -o %t.bolt -data %t/yaml -infer-stale-profile -v=2 \ +# RUN: --stale-matching-with-pseudo-probes 2>&1 | FileCheck %s + +# CHECK: BOLT-WARNING: 3 (100.0% of all profiled) functions have invalid (possibly stale) profile +# CHECK: BOLT-INFO: inference found an exact pseudo probe match for 100.00% of basic blocks (3 out of 3 stale) + +#--- yaml +--- +header: + profile-version: 1 + binary-name: 'inline-cs-pseudoprobe.perfbin' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: perf data aggregator + profile-events: '' + dfs-order: false + hash-func: xxh3 +functions: + - name: bar + fid: 9 + hash: 0x1 + exec: 1 + nblocks: 1 + blocks: + - bid: 0 + insns: 11 + hash: 0x1 + exec: 1 + probes: [ { blx: 9 } ] + inline_tree: [ { } ] + - name: foo + fid: 10 + hash: 0x2 + exec: 1 + nblocks: 6 + blocks: + - bid: 0 + insns: 3 + hash: 0x2 + exec: 1 + succ: [ { bid: 3, cnt: 0 } ] + probes: [ { blx: 3 } ] + inline_tree: [ { g: 1 }, { g: 0, cs: 8 } ] + - name: main + fid: 11 + hash: 0x3 + exec: 1 + nblocks: 6 + blocks: + - bid: 0 + insns: 3 + hash: 0x3 + exec: 1 + succ: [ { bid: 3, cnt: 0 } ] + probes: [ { blx: 3, id: 1 }, { blx: 1 } ] + inline_tree: [ { g: 2 }, { g: 1, cs: 2 }, { g: 0, p: 1, cs: 8 } ] +pseudo_probe_desc: + gs: [ 0xE413754A191DB537, 0x5CF8C24CDB18BDAC, 0xDB956436E78DD5FA ] + gh: [ 2, 0, 1 ] + hs: [ 0x200205A19C5B4, 0x10000FFFFFFFF, 0x10E852DA94 ] +... diff --git a/bolt/test/X86/match-blocks-with-pseudo-probes.test b/bolt/test/X86/match-blocks-with-pseudo-probes.test new file mode 100644 index 0000000000000000000000000000000000000000..40cb64ee82919abcacf5007430ed95ed7fdb30a3 --- /dev/null +++ b/bolt/test/X86/match-blocks-with-pseudo-probes.test @@ -0,0 +1,63 @@ +## Tests stale block matching with pseudo probes. + +# REQUIRES: system-linux +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml -v=2 \ +# RUN: --print-cfg --funcs=main --infer-stale-profile \ +# RUN: --stale-matching-with-pseudo-probes 2>&1 | FileCheck %s + +# CHECK: BOLT-INFO: inference found an exact pseudo probe match for 100.00% of basic blocks (1 out of 1 stale) + +#--- main.s + .text + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +# %bb.0: + pushq %rbp + movq %rsp, %rbp + movl $0, -4(%rbp) + .pseudoprobe 15822663052811949562 1 0 0 main + xorl %eax, %eax + popq %rbp + retq +.Lfunc_end0: + .size main, .Lfunc_end0-main + # -- End function + .section .pseudo_probe_desc,"",@progbits + .quad -2624081020897602054 + .quad 4294967295 + .byte 4 + .ascii "main" + +#--- yaml +--- +header: + profile-version: 1 + binary-name: 'match-blocks-with-pseudo-probes.s.tmp.exe' + binary-build-id: '' + profile-flags: [ lbr ] + profile-origin: branch profile reader + profile-events: '' + dfs-order: false + hash-func: xxh3 +functions: + - name: main + fid: 0 + hash: 0x0000000000000001 + exec: 1 + nblocks: 6 + blocks: + - bid: 1 + hash: 0xFFFFFFFFFFFFFFF1 + insns: 1 + succ: [ { bid: 3, cnt: 1} ] + probes: [ { blx: 1 } ] + inline_tree: [ { g: 0 } ] +pseudo_probe_desc: + gs: [ 0xDB956436E78DD5FA ] + gh: [ 0 ] + hs: [ 0xFFFFFFFF ] diff --git a/bolt/test/X86/match-functions-with-calls-as-anchors.test b/bolt/test/X86/match-functions-with-calls-as-anchors.test index 984d614fbf85f97e7ee2d33056f27e60cde6a757..f8ef2880a6ce9abc4146899748a138615e7c8f90 100644 --- a/bolt/test/X86/match-functions-with-calls-as-anchors.test +++ b/bolt/test/X86/match-functions-with-calls-as-anchors.test @@ -5,15 +5,16 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o # RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib # RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml --profile-ignore-hash -v=1 \ -# RUN: --dyno-stats --print-cfg --infer-stale-profile=1 --debug 2>&1 | FileCheck %s +# RUN: --dyno-stats --print-cfg --infer-stale-profile=1 --debug-only=bolt-prof \ +# RUN: 2>&1 | FileCheck %s # CHECK: BOLT-INFO: applying profile inference for "qux" # CHECK: Matched yaml block (bid = 1) with hash 4 to BB (index = 0) with hash 314e1bc10000 -# CHECK: loose match +# CHECK: call match # CHECK: BOLT-INFO: applying profile inference for "fred" # CHECK: Matched yaml block (bid = 1) with hash 5 to BB (index = 0) with hash 7541bc10000 -# CHECK: loose match +# CHECK: call match #--- main.s .globl foo # -- Begin function foo diff --git a/bolt/test/X86/reader-stale-yaml.test b/bolt/test/X86/reader-stale-yaml.test index 378abc38252462d4bbaaae4a2bcd9936905904fe..7a9540c48f80dfc046983ebf42411c526c3b99b9 100644 --- a/bolt/test/X86/reader-stale-yaml.test +++ b/bolt/test/X86/reader-stale-yaml.test @@ -77,10 +77,10 @@ CHECK2: pre-processing profile using YAML profile reader CHECK2: applying profile inference for "SolveCubic" CHECK2: Matched yaml block (bid = 0) with hash 4600940a609c0000 to BB (index = 0) with hash 4600940a609c0000 CHECK2-NEXT: exact match -CHECK2: Matched yaml block (bid = 1) with hash 167a1f084f130088 to BB (index = 1) with hash 167a1f084f130088 -CHECK2-NEXT: exact match CHECK2: Matched yaml block (bid = 13) with hash a8d50000f81902a7 to BB (index = 13) with hash a8d5aa43f81902a7 CHECK2-NEXT: loose match +CHECK2: Matched yaml block (bid = 1) with hash 167a1f084f130088 to BB (index = 1) with hash 167a1f084f130088 +CHECK2-NEXT: exact match CHECK2: Matched yaml block (bid = 3) with hash c516000073dc00a0 to BB (index = 3) with hash c516b1c973dc00a0 CHECK2-NEXT: loose match CHECK2: Matched yaml block (bid = 5) with hash 6446e1ea500111 to BB (index = 5) with hash 6446e1ea500111 diff --git a/bolt/test/eh-frame-hdr.test b/bolt/test/eh-frame-hdr.test new file mode 100644 index 0000000000000000000000000000000000000000..4d718c850e2f283138b891ac4a5b887fdbfbd5d4 --- /dev/null +++ b/bolt/test/eh-frame-hdr.test @@ -0,0 +1,12 @@ +# Check that llvm-bolt overwrites .eh_frame_hdr in-place. + +REQUIRES: system-linux + +RUN: %clang %cflags %p/Inputs/hello.c -o %t -Wl,-q +RUN: llvm-bolt %t -o %t.bolt --use-old-text \ +RUN: | FileCheck %s --check-prefix=CHECK-BOLT +RUN: llvm-readelf -WS %t.bolt | FileCheck %s + +CHECK-BOLT: rewriting .eh_frame_hdr in-place + +CHECK-NOT: .bolt.org.eh_frame_hdr diff --git a/bolt/test/eh-frame-overwrite.test b/bolt/test/eh-frame-overwrite.test new file mode 100644 index 0000000000000000000000000000000000000000..649d739ec6086a2bc12b246cd348019441213fe8 --- /dev/null +++ b/bolt/test/eh-frame-overwrite.test @@ -0,0 +1,8 @@ +# Check that llvm-bolt can overwrite .eh_frame section in-place. + +REQUIRES: system-linux + +RUN: %clang %cflags %p/Inputs/hello.c -o %t -Wl,-q +RUN: llvm-bolt %t -o %t.bolt --strict | FileCheck %s + +CHECK: rewriting .eh_frame in-place diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp index c66c2d0c0fb16e2a6b66f63e27f7789fcbd7f1e3..cd6f24c4570a798cb5480a3950872d0169f3da61 100644 --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -90,14 +90,15 @@ INSTANTIATE_TEST_SUITE_P(AArch64, MCPlusBuilderTester, ::testing::Values(Triple::aarch64)); TEST_P(MCPlusBuilderTester, AliasX0) { - uint64_t AliasesX0[] = {AArch64::W0, AArch64::X0, AArch64::W0_W1, + uint64_t AliasesX0[] = {AArch64::W0, AArch64::W0_HI, + AArch64::X0, AArch64::W0_W1, AArch64::X0_X1, AArch64::X0_X1_X2_X3_X4_X5_X6_X7}; size_t AliasesX0Count = sizeof(AliasesX0) / sizeof(*AliasesX0); testRegAliases(Triple::aarch64, AArch64::X0, AliasesX0, AliasesX0Count); } TEST_P(MCPlusBuilderTester, AliasSmallerX0) { - uint64_t AliasesX0[] = {AArch64::W0, AArch64::X0}; + uint64_t AliasesX0[] = {AArch64::W0, AArch64::W0_HI, AArch64::X0}; size_t AliasesX0Count = sizeof(AliasesX0) / sizeof(*AliasesX0); testRegAliases(Triple::aarch64, AArch64::X0, AliasesX0, AliasesX0Count, true); } diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp index 354f35cbadbeb9470af81324b4559901dfe9cd31..bba8f8acc77da9a81e7a2d814987791aef09b5ae 100644 --- a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp @@ -95,7 +95,8 @@ bool IncludeFixerActionFactory::runInvocation( // Create the compiler's actual diagnostics engine. We want to drop all // diagnostics here. - Compiler.createDiagnostics(new clang::IgnoringDiagConsumer, + Compiler.createDiagnostics(Files->getVirtualFileSystem(), + new clang::IgnoringDiagConsumer, /*ShouldOwnClient=*/true); Compiler.createSourceManager(*Files); diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 620a57194acb8e692bf7fd71b29fd7e476a65ccb..3d1f63fcf33a5ad229725ceec231b45f3f2abc70 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -20,7 +20,7 @@ namespace { AST_MATCHER_P(FunctionDecl, isEnabled, llvm::StringSet<>, FunctionsThatShouldNotThrow) { - return FunctionsThatShouldNotThrow.count(Node.getNameAsString()) > 0; + return FunctionsThatShouldNotThrow.contains(Node.getNameAsString()); } AST_MATCHER(FunctionDecl, isExplicitThrow) { diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index 8f4b5e8092ddaaeb766fa7e626815c27c554f85f..960133159dbbf58e8d9522bb08739142b523daed 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -315,9 +315,10 @@ void UseAfterMoveFinder::getReinits( "::std::unordered_map", "::std::unordered_multiset", "::std::unordered_multimap")))))); - auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType( - recordType(hasDeclaration(cxxRecordDecl(hasAnyName( - "::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr")))))); + auto StandardResettableOwnerTypeMatcher = hasType( + hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl( + hasAnyName("::std::unique_ptr", "::std::shared_ptr", + "::std::weak_ptr", "::std::optional", "::std::any")))))); // Matches different types of reinitialization. auto ReinitMatcher = @@ -340,7 +341,7 @@ void UseAfterMoveFinder::getReinits( callee(cxxMethodDecl(hasAnyName("clear", "assign")))), // reset() on standard smart pointers. cxxMemberCallExpr( - on(expr(DeclRefMatcher, StandardSmartPointerTypeMatcher)), + on(expr(DeclRefMatcher, StandardResettableOwnerTypeMatcher)), callee(cxxMethodDecl(hasName("reset")))), // Methods that have the [[clang::reinitializes]] attribute. cxxMemberCallExpr( diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp index bebdce525e28871f8361607190aa84e82475d2fb..76fa2d916f0e86050e036d06c9ae9258ae267b9f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp @@ -112,7 +112,7 @@ static bool checkOverridingFunctionReturnType(const ASTContext *Context, // The class type D should have the same cv-qualification as or less // cv-qualification than the class type B. - if (DTy.isMoreQualifiedThan(BTy)) + if (DTy.isMoreQualifiedThan(BTy, *Context)) return false; return true; diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp index 18420d0c8488d2192b23e9033c7827a88021fdc9..c5eaff88e0ed3b9a631420217cf93c0eb82a55c4 100644 --- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp @@ -299,10 +299,11 @@ static bool applyDiceHeuristic(StringRef Arg, StringRef Param, /// Checks if ArgType binds to ParamType regarding reference-ness and /// cv-qualifiers. -static bool areRefAndQualCompatible(QualType ArgType, QualType ParamType) { +static bool areRefAndQualCompatible(QualType ArgType, QualType ParamType, + const ASTContext &Ctx) { return !ParamType->isReferenceType() || ParamType.getNonReferenceType().isAtLeastAsQualifiedAs( - ArgType.getNonReferenceType()); + ArgType.getNonReferenceType(), Ctx); } static bool isPointerOrArray(QualType TypeToCheck) { @@ -311,12 +312,12 @@ static bool isPointerOrArray(QualType TypeToCheck) { /// Checks whether ArgType is an array type identical to ParamType's array type. /// Enforces array elements' qualifier compatibility as well. -static bool isCompatibleWithArrayReference(QualType ArgType, - QualType ParamType) { +static bool isCompatibleWithArrayReference(QualType ArgType, QualType ParamType, + const ASTContext &Ctx) { if (!ArgType->isArrayType()) return false; // Here, qualifiers belong to the elements of the arrays. - if (!ParamType.isAtLeastAsQualifiedAs(ArgType)) + if (!ParamType.isAtLeastAsQualifiedAs(ArgType, Ctx)) return false; return ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType(); @@ -342,12 +343,13 @@ static QualType convertToPointeeOrArrayElementQualType(QualType TypeToConvert) { /// every * in ParamType to the right of that cv-qualifier, except the last /// one, must also be const-qualified. static bool arePointersStillQualCompatible(QualType ArgType, QualType ParamType, - bool &IsParamContinuouslyConst) { + bool &IsParamContinuouslyConst, + const ASTContext &Ctx) { // The types are compatible, if the parameter is at least as qualified as the // argument, and if it is more qualified, it has to be const on upper pointer // levels. bool AreTypesQualCompatible = - ParamType.isAtLeastAsQualifiedAs(ArgType) && + ParamType.isAtLeastAsQualifiedAs(ArgType, Ctx) && (!ParamType.hasQualifiers() || IsParamContinuouslyConst); // Check whether the parameter's constness continues at the current pointer // level. @@ -359,9 +361,10 @@ static bool arePointersStillQualCompatible(QualType ArgType, QualType ParamType, /// Checks whether multilevel pointers are compatible in terms of levels, /// qualifiers and pointee type. static bool arePointerTypesCompatible(QualType ArgType, QualType ParamType, - bool IsParamContinuouslyConst) { + bool IsParamContinuouslyConst, + const ASTContext &Ctx) { if (!arePointersStillQualCompatible(ArgType, ParamType, - IsParamContinuouslyConst)) + IsParamContinuouslyConst, Ctx)) return false; do { @@ -372,7 +375,7 @@ static bool arePointerTypesCompatible(QualType ArgType, QualType ParamType, // Check whether cv-qualifiers permit compatibility on // current level. if (!arePointersStillQualCompatible(ArgType, ParamType, - IsParamContinuouslyConst)) + IsParamContinuouslyConst, Ctx)) return false; if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType()) @@ -396,7 +399,7 @@ static bool areTypesCompatible(QualType ArgType, QualType ParamType, return true; // Check for constness and reference compatibility. - if (!areRefAndQualCompatible(ArgType, ParamType)) + if (!areRefAndQualCompatible(ArgType, ParamType, Ctx)) return false; bool IsParamReference = ParamType->isReferenceType(); @@ -434,7 +437,7 @@ static bool areTypesCompatible(QualType ArgType, QualType ParamType, // When ParamType is an array reference, ArgType has to be of the same-sized // array-type with cv-compatible element type. if (IsParamReference && ParamType->isArrayType()) - return isCompatibleWithArrayReference(ArgType, ParamType); + return isCompatibleWithArrayReference(ArgType, ParamType, Ctx); bool IsParamContinuouslyConst = !IsParamReference || ParamType.getNonReferenceType().isConstQualified(); @@ -444,7 +447,7 @@ static bool areTypesCompatible(QualType ArgType, QualType ParamType, ParamType = convertToPointeeOrArrayElementQualType(ParamType); // Check qualifier compatibility on the next level. - if (!ParamType.isAtLeastAsQualifiedAs(ArgType)) + if (!ParamType.isAtLeastAsQualifiedAs(ArgType, Ctx)) return false; if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType()) @@ -472,8 +475,8 @@ static bool areTypesCompatible(QualType ArgType, QualType ParamType, if (!(ParamType->isAnyPointerType() && ArgType->isAnyPointerType())) return false; - return arePointerTypesCompatible(ArgType, ParamType, - IsParamContinuouslyConst); + return arePointerTypesCompatible(ArgType, ParamType, IsParamContinuouslyConst, + Ctx); } static bool isOverloadedUnaryOrBinarySymbolOperator(const FunctionDecl *FD) { diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 9bfb7e2677533a1d1429adb5d786d2826b851bd1..68f3ecf6bdaa8166811eecc83f86a4b4e90a3a1c 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -418,7 +418,7 @@ ExceptionAnalyzer::ExceptionInfo::filterIgnoredExceptions( if (TD->getDeclName().isIdentifier()) { if ((IgnoreBadAlloc && (TD->getName() == "bad_alloc" && TD->isInStdNamespace())) || - (IgnoredTypes.count(TD->getName()) > 0)) + (IgnoredTypes.contains(TD->getName()))) TypesToDelete.push_back(T); } } @@ -449,7 +449,8 @@ void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() { ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( const FunctionDecl *Func, const ExceptionInfo::Throwables &Caught, llvm::SmallSet &CallStack) { - if (!Func || CallStack.count(Func) || (!CallStack.empty() && !canThrow(Func))) + if (!Func || CallStack.contains(Func) || + (!CallStack.empty() && !canThrow(Func))) return ExceptionInfo::createNonThrowing(); if (const Stmt *Body = Func->getBody()) { @@ -507,7 +508,7 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( for (unsigned I = 0; I < Try->getNumHandlers(); ++I) { const CXXCatchStmt *Catch = Try->getHandler(I); - // Everything is catched through 'catch(...)'. + // Everything is caught through 'catch(...)'. if (!Catch->getExceptionDecl()) { ExceptionInfo Rethrown = throwsException( Catch->getHandlerBlock(), Uncaught.getExceptionTypes(), CallStack); diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h index 0a8cf8668d3ca9a64ee46b1b37e532d48fa40565..6c2d693d64b50e414bc21a92e4cece7e7fa24be5 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h @@ -101,8 +101,8 @@ public: /// Recalculate the 'Behaviour' for example after filtering. void reevaluateBehaviour(); - /// Keep track if the entity related to this 'ExceptionInfo' can in princple - /// throw, if it's unknown or if it won't throw. + /// Keep track if the entity related to this 'ExceptionInfo' can in + /// principle throw, if it's unknown or if it won't throw. State Behaviour; /// Keep track if the entity contains any unknown elements to keep track diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 06573a57554245184e8640344884149639d80e4d..05dd313d0a0d357c659f50cfdf87a5c16f266854 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -1419,15 +1419,12 @@ void ClangdLSPServer::applyConfiguration( const ConfigurationSettings &Settings) { // Per-file update to the compilation database. llvm::StringSet<> ModifiedFiles; - for (auto &Entry : Settings.compilationDatabaseChanges) { - PathRef File = Entry.first; - auto Old = CDB->getCompileCommand(File); - auto New = - tooling::CompileCommand(std::move(Entry.second.workingDirectory), File, - std::move(Entry.second.compilationCommand), + for (auto &[File, Command] : Settings.compilationDatabaseChanges) { + auto Cmd = + tooling::CompileCommand(std::move(Command.workingDirectory), File, + std::move(Command.compilationCommand), /*Output=*/""); - if (Old != New) { - CDB->setCompileCommand(File, std::move(New)); + if (CDB->setCompileCommand(File, std::move(Cmd))) { ModifiedFiles.insert(File); } } diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp index c60ab8e1b8062a85646ad62feb80f1e3fcc26a03..161cc9ae0ca365cc739c3bbd5c5c5e0402c99980 100644 --- a/clang-tools-extra/clangd/Compiler.cpp +++ b/clang-tools-extra/clangd/Compiler.cpp @@ -110,8 +110,8 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, CIOpts.VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory); CIOpts.CC1Args = CC1Args; CIOpts.RecoverOnError = true; - CIOpts.Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, false); + CIOpts.Diags = CompilerInstance::createDiagnostics( + *CIOpts.VFS, new DiagnosticOptions, &D, false); CIOpts.ProbePrecompiled = false; std::unique_ptr CI = createInvocation(ArgStrs, CIOpts); if (!CI) @@ -148,7 +148,7 @@ prepareCompilerInstance(std::unique_ptr CI, auto Clang = std::make_unique( std::make_shared()); Clang->setInvocation(std::move(CI)); - Clang->createDiagnostics(&DiagsClient, false); + Clang->createDiagnostics(*VFS, &DiagsClient, false); if (auto VFSWithRemapping = createVFSFromCompilerInvocation( Clang->getInvocation(), Clang->getDiagnostics(), VFS)) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 1d96667a8e9f4a79d6341dcc8e522d2f3783f13c..71e97ac4efd673b157cbe8179d6507146dd7f6b3 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -807,7 +807,7 @@ tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const { return Cmd; } -void OverlayCDB::setCompileCommand(PathRef File, +bool OverlayCDB::setCompileCommand(PathRef File, std::optional Cmd) { // We store a canonical version internally to prevent mismatches between set // and get compile commands. Also it assures clients listening to broadcasts @@ -815,12 +815,19 @@ void OverlayCDB::setCompileCommand(PathRef File, std::string CanonPath = removeDots(File); { std::unique_lock Lock(Mutex); - if (Cmd) - Commands[CanonPath] = std::move(*Cmd); - else + if (Cmd) { + if (auto [It, Inserted] = + Commands.try_emplace(CanonPath, std::move(*Cmd)); + !Inserted) { + if (It->second == *Cmd) + return false; + It->second = *Cmd; + } + } else Commands.erase(CanonPath); } OnCommandChanged.broadcast({CanonPath}); + return true; } DelegatingCDB::DelegatingCDB(const GlobalCompilationDatabase *Base) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h index ea999fe8aee0177a13e563ea8105aa9b87a28f78..f8349c6efecb01f85bef834a27d6c99c715607db 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -203,7 +203,9 @@ public: tooling::CompileCommand getFallbackCommand(PathRef File) const override; /// Sets or clears the compilation command for a particular file. - void + /// Returns true if the command was changed (including insertion and removal), + /// false if it was unchanged. + bool setCompileCommand(PathRef File, std::optional CompilationCommand); diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp index 2bce3a2082561610ee6336cc7fda71ec0673efe1..29508901f85bba8ec99739890b20dc670b7c6bda 100644 --- a/clang-tools-extra/clangd/ModulesBuilder.cpp +++ b/clang-tools-extra/clangd/ModulesBuilder.cpp @@ -188,7 +188,8 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath, clang::clangd::IgnoreDiagnostics IgnoreDiags; IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions, &IgnoreDiags, + CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions, + &IgnoreDiags, /*ShouldOwnClient=*/false); LangOptions LangOpts; diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp index c14c4d1ba103f85080646d4291246b86475413e4..ce88ec0eb88c1beb44c629c7e20251db92d58850 100644 --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -613,8 +613,9 @@ buildPreamble(PathRef FileName, CompilerInvocation CI, for (const auto &L : ASTListeners) L->sawDiagnostic(D, Diag); }); + auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory); llvm::IntrusiveRefCntPtr PreambleDiagsEngine = - CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), + CompilerInstance::createDiagnostics(*VFS, &CI.getDiagnosticOpts(), &PreambleDiagnostics, /*ShouldOwnClient=*/false); const Config &Cfg = Config::current(); @@ -651,7 +652,6 @@ buildPreamble(PathRef FileName, CompilerInvocation CI, for (const auto &L : ASTListeners) L->beforeExecute(CI); }); - auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory); llvm::SmallString<32> AbsFileName(FileName); VFS->makeAbsolute(AbsFileName); auto StatCache = std::make_shared(AbsFileName); diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 761f96846d45389cdf374e681a6f592516128fd4..05c8041df7de75ed24fc2e9df470c7b50bbef369 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -511,6 +511,35 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R, if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor")) R.CompletionFixes |= *EditsNearCursor; } + if (auto *References = TextDocument->getObject("references")) { + if (auto ContainerSupport = References->getBoolean("container")) { + R.ReferenceContainer |= *ContainerSupport; + } + } + if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) { + if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline")) { + R.DiagnosticFixes |= *CodeActions; + } + } + if (auto *InactiveRegions = + TextDocument->getObject("inactiveRegionsCapabilities")) { + if (auto InactiveRegionsSupport = + InactiveRegions->getBoolean("inactiveRegions")) { + R.InactiveRegions |= *InactiveRegionsSupport; + } + } + } + if (auto *Window = Experimental->getObject("window")) { + if (auto Implicit = + Window->getBoolean("implicitWorkDoneProgressCreate")) { + R.ImplicitProgressCreation |= *Implicit; + } + } + if (auto *OffsetEncoding = Experimental->get("offsetEncoding")) { + R.offsetEncoding.emplace(); + if (!fromJSON(*OffsetEncoding, *R.offsetEncoding, + P.field("offsetEncoding"))) + return false; } } diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 5b28095758198d1c38d66735290f37ad2aa0624b..c7ef1a13e6e39ec5c4909af3f12248888738439f 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -452,6 +452,7 @@ struct ClientCapabilities { std::optional WorkspaceSymbolKinds; /// Whether the client accepts diagnostics with codeActions attached inline. + /// This is a clangd extension. /// textDocument.publishDiagnostics.codeActionsInline. bool DiagnosticFixes = false; @@ -475,6 +476,7 @@ struct ClientCapabilities { /// Client supports displaying a container string for results of /// textDocument/reference (clangd extension) + /// textDocument.references.container bool ReferenceContainer = false; /// Client supports hierarchical document symbols. @@ -563,6 +565,7 @@ struct ClientCapabilities { /// Whether the client supports the textDocument/inactiveRegions /// notification. This is a clangd extension. + /// textDocument.inactiveRegionsCapabilities.inactiveRegions bool InactiveRegions = false; }; bool fromJSON(const llvm::json::Value &, ClientCapabilities &, diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 4fd11307857ff84dcfbf38b67dedf7e030fe1ee8..61fa66180376cd1e7194091626ffd1acbe9a1759 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -63,6 +63,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include @@ -2275,7 +2276,7 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) { // Initially store the ranges in a map keyed by SymbolID of the caller. // This allows us to group different calls with the same caller // into the same CallHierarchyIncomingCall. - llvm::DenseMap> CallsIn; + llvm::DenseMap> CallsIn; // We can populate the ranges based on a refs request only. As we do so, we // also accumulate the container IDs into a lookup request. LookupRequest ContainerLookup; @@ -2285,7 +2286,7 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) { elog("incomingCalls failed to convert location: {0}", Loc.takeError()); return; } - CallsIn[R.Container].push_back(Loc->range); + CallsIn[R.Container].push_back(*Loc); ContainerLookup.IDs.insert(R.Container); }); @@ -2294,9 +2295,21 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) { Index->lookup(ContainerLookup, [&](const Symbol &Caller) { auto It = CallsIn.find(Caller.ID); assert(It != CallsIn.end()); - if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file())) + if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file())) { + std::vector FromRanges; + for (const Location &L : It->second) { + if (L.uri != CHI->uri) { + // Call location not in same file as caller. + // This can happen in some edge cases. There's not much we can do, + // since the protocol only allows returning ranges interpreted as + // being in the caller's file. + continue; + } + FromRanges.push_back(L.range); + } Results.push_back( - CallHierarchyIncomingCall{std::move(*CHI), std::move(It->second)}); + CallHierarchyIncomingCall{std::move(*CHI), std::move(FromRanges)}); + } }); // Sort results by name of container. llvm::sort(Results, [](const CallHierarchyIncomingCall &A, diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp index 591a8b245260eab6c43a1bb7e385d3733e65623d..789c10bdd4822ae3aa02be42cc60c1c26a123a72 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp @@ -109,14 +109,13 @@ findContextForNS(llvm::StringRef TargetNS, const DeclContext *CurContext) { // afterwards it can be shared with define-inline code action. llvm::Expected getFunctionSourceAfterReplacements(const FunctionDecl *FD, - const tooling::Replacements &Replacements) { + const tooling::Replacements &Replacements, + bool TargetFileIsHeader) { const auto &SM = FD->getASTContext().getSourceManager(); auto OrigFuncRange = toHalfOpenFileRange( SM, FD->getASTContext().getLangOpts(), FD->getSourceRange()); if (!OrigFuncRange) return error("Couldn't get range for function."); - assert(!FD->getDescribedFunctionTemplate() && - "Define out-of-line doesn't apply to function templates."); // Get new begin and end positions for the qualified function definition. unsigned FuncBegin = SM.getFileOffset(OrigFuncRange->getBegin()); @@ -129,24 +128,38 @@ getFunctionSourceAfterReplacements(const FunctionDecl *FD, if (!QualifiedFunc) return QualifiedFunc.takeError(); + auto Source = QualifiedFunc->substr(FuncBegin, FuncEnd - FuncBegin + 1); std::string TemplatePrefix; + auto AddToTemplatePrefixIfApplicable = [&](const Decl *D) { + const TemplateParameterList *Params = D->getDescribedTemplateParams(); + if (!Params) + return; + for (Decl *P : *Params) { + if (auto *TTP = dyn_cast(P)) + TTP->removeDefaultArgument(); + else if (auto *NTTP = dyn_cast(P)) + NTTP->removeDefaultArgument(); + else if (auto *TTPD = dyn_cast(P)) + TTPD->removeDefaultArgument(); + } + std::string S; + llvm::raw_string_ostream Stream(S); + Params->print(Stream, FD->getASTContext()); + if (!S.empty()) + *S.rbegin() = '\n'; // Replace space with newline + TemplatePrefix.insert(0, S); + }; + AddToTemplatePrefixIfApplicable(FD); if (auto *MD = llvm::dyn_cast(FD)) { for (const CXXRecordDecl *Parent = MD->getParent(); Parent; Parent = llvm::dyn_cast_or_null(Parent->getParent())) { - if (const TemplateParameterList *Params = - Parent->getDescribedTemplateParams()) { - std::string S; - llvm::raw_string_ostream Stream(S); - Params->print(Stream, FD->getASTContext()); - if (!S.empty()) - *S.rbegin() = '\n'; // Replace space with newline - TemplatePrefix.insert(0, S); - } + AddToTemplatePrefixIfApplicable(Parent); } } - auto Source = QualifiedFunc->substr(FuncBegin, FuncEnd - FuncBegin + 1); + if (TargetFileIsHeader) + Source.insert(0, "inline "); if (!TemplatePrefix.empty()) Source.insert(0, TemplatePrefix); return Source; @@ -202,7 +215,8 @@ deleteTokensWithKind(const syntax::TokenBuffer &TokBuf, tok::TokenKind Kind, llvm::Expected getFunctionSourceCode(const FunctionDecl *FD, const DeclContext *TargetContext, const syntax::TokenBuffer &TokBuf, - const HeuristicResolver *Resolver) { + const HeuristicResolver *Resolver, + bool TargetFileIsHeader) { auto &AST = FD->getASTContext(); auto &SM = AST.getSourceManager(); @@ -225,6 +239,8 @@ getFunctionSourceCode(const FunctionDecl *FD, const DeclContext *TargetContext, return; for (const NamedDecl *ND : Ref.Targets) { + if (ND->getKind() == Decl::TemplateTypeParm) + return; if (ND->getDeclContext() != Ref.Targets.front()->getDeclContext()) { elog("Targets from multiple contexts: {0}, {1}", printQualifiedName(*Ref.Targets.front()), @@ -337,7 +353,8 @@ getFunctionSourceCode(const FunctionDecl *FD, const DeclContext *TargetContext, if (Errors) return std::move(Errors); - return getFunctionSourceAfterReplacements(FD, DeclarationCleanups); + return getFunctionSourceAfterReplacements(FD, DeclarationCleanups, + TargetFileIsHeader); } struct InsertionPoint { @@ -419,15 +436,15 @@ public: Source->isOutOfLine()) return false; - // Bail out if this is a function template or specialization, as their + // Bail out if this is a function template specialization, as their // definitions need to be visible in all including translation units. - if (Source->getDescribedFunctionTemplate()) - return false; if (Source->getTemplateSpecializationInfo()) return false; auto *MD = llvm::dyn_cast(Source); if (!MD) { + if (Source->getDescribedFunctionTemplate()) + return false; // Can't outline free-standing functions in the same file. return !SameFile; } @@ -450,6 +467,19 @@ public: } } + // For function templates, the same limitations as for class templates + // apply. + if (const TemplateParameterList *Params = + MD->getDescribedTemplateParams()) { + // FIXME: Is this really needed? It inhibits application on + // e.g. std::enable_if. + for (NamedDecl *P : *Params) { + if (!P->getIdentifier()) + return false; + } + SameFile = true; + } + // The refactoring is meaningless for unnamed classes and namespaces, // unless we're outlining in the same file for (const DeclContext *DC = MD->getParent(); DC; DC = DC->getParent()) { @@ -485,7 +515,8 @@ public: auto FuncDef = getFunctionSourceCode( Source, InsertionPoint->EnclosingNamespace, Sel.AST->getTokens(), - Sel.AST->getHeuristicResolver()); + Sel.AST->getHeuristicResolver(), + SameFile && isHeaderFile(Sel.AST->tuPath(), Sel.AST->getLangOpts())); if (!FuncDef) return FuncDef.takeError(); diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp index 0302839c58252e747778c4091352fa148933b5c2..cd07cbf73635c267e74166fbd471c487eba3e03f 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp @@ -56,6 +56,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" @@ -70,7 +71,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" -#include "llvm/Support/raw_os_ostream.h" #include namespace clang { @@ -95,8 +95,8 @@ enum FunctionDeclKind { OutOfLineDefinition }; -// A RootStmt is a statement that's fully selected including all it's children -// and it's parent is unselected. +// A RootStmt is a statement that's fully selected including all its children +// and its parent is unselected. // Check if a node is a root statement. bool isRootStmt(const Node *N) { if (!N->ASTNode.get()) @@ -104,9 +104,12 @@ bool isRootStmt(const Node *N) { // Root statement cannot be partially selected. if (N->Selected == SelectionTree::Partial) return false; - // Only DeclStmt can be an unselected RootStmt since VarDecls claim the entire - // selection range in selectionTree. - if (N->Selected == SelectionTree::Unselected && !N->ASTNode.get()) + // A DeclStmt can be an unselected RootStmt since VarDecls claim the entire + // selection range in selectionTree. Additionally, a CXXOperatorCallExpr of a + // binary operation can be unselected because its children claim the entire + // selection range in the selection tree (e.g. <<). + if (N->Selected == SelectionTree::Unselected && !N->ASTNode.get() && + !N->ASTNode.get()) return false; return true; } @@ -913,8 +916,8 @@ Expected ExtractFunction::apply(const Selection &Inputs) { tooling::Replacements OtherEdit( createForwardDeclaration(*ExtractedFunc, SM)); - if (auto PathAndEdit = Tweak::Effect::fileEdit(SM, SM.getFileID(*FwdLoc), - OtherEdit)) + if (auto PathAndEdit = + Tweak::Effect::fileEdit(SM, SM.getFileID(*FwdLoc), OtherEdit)) MultiFileEffect->ApplyEdits.try_emplace(PathAndEdit->first, PathAndEdit->second); else diff --git a/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp index b2278ff12735dc10ab359fa2ebffd7507f47ebd4..8821d3aad9c784a25c307f8053acce22ac50c9f7 100644 --- a/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp +++ b/clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp @@ -491,6 +491,35 @@ TEST(CallHierarchy, HierarchyOnVar) { fromRanges(Source.range("Callee"))))); } +TEST(CallHierarchy, CallInDifferentFileThanCaller) { + Annotations Header(R"cpp( + #define WALDO void caller() { + )cpp"); + Annotations Source(R"cpp( + void call^ee(); + WALDO + callee(); + } + )cpp"); + auto TU = TestTU::withCode(Source.code()); + TU.HeaderCode = Header.code(); + auto AST = TU.build(); + auto Index = TU.index(); + + std::vector Items = + prepareCallHierarchy(AST, Source.point(), testPath(TU.Filename)); + ASSERT_THAT(Items, ElementsAre(withName("callee"))); + + auto Incoming = incomingCalls(Items[0], Index.get()); + + // The only call site is in the source file, which is a different file from + // the declaration of the function containing the call, which is in the + // header. The protocol does not allow us to represent such calls, so we drop + // them. (The call hierarchy item itself is kept.) + EXPECT_THAT(Incoming, + ElementsAre(AllOf(from(withName("caller")), fromRanges()))); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp index a2ffdefe1bbcb2d7b1ef5fff183a5fef533a3284..c9e01e52dac1f3a6285000813e1526c9eb7d136c 100644 --- a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp +++ b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp @@ -92,11 +92,13 @@ TEST_F(OverlayCDBTest, GetCompileCommand) { EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), std::nullopt); auto Override = cmd(testPath("foo.cc"), "-DA=3"); - CDB.setCompileCommand(testPath("foo.cc"), Override); + EXPECT_TRUE(CDB.setCompileCommand(testPath("foo.cc"), Override)); + EXPECT_FALSE(CDB.setCompileCommand(testPath("foo.cc"), Override)); EXPECT_THAT(CDB.getCompileCommand(testPath("foo.cc"))->CommandLine, Contains("-DA=3")); EXPECT_EQ(CDB.getCompileCommand(testPath("missing.cc")), std::nullopt); - CDB.setCompileCommand(testPath("missing.cc"), Override); + EXPECT_TRUE(CDB.setCompileCommand(testPath("missing.cc"), Override)); + EXPECT_FALSE(CDB.setCompileCommand(testPath("missing.cc"), Override)); EXPECT_THAT(CDB.getCompileCommand(testPath("missing.cc"))->CommandLine, Contains("-DA=3")); } @@ -111,7 +113,7 @@ TEST_F(OverlayCDBTest, NoBase) { OverlayCDB CDB(nullptr, {"-DA=6"}); EXPECT_EQ(CDB.getCompileCommand(testPath("bar.cc")), std::nullopt); auto Override = cmd(testPath("bar.cc"), "-DA=5"); - CDB.setCompileCommand(testPath("bar.cc"), Override); + EXPECT_TRUE(CDB.setCompileCommand(testPath("bar.cc"), Override)); EXPECT_THAT(CDB.getCompileCommand(testPath("bar.cc"))->CommandLine, Contains("-DA=5")); @@ -128,10 +130,10 @@ TEST_F(OverlayCDBTest, Watch) { Changes.push_back(ChangedFiles); }); - Inner.setCompileCommand("A.cpp", tooling::CompileCommand()); - Outer.setCompileCommand("B.cpp", tooling::CompileCommand()); - Inner.setCompileCommand("A.cpp", std::nullopt); - Outer.setCompileCommand("C.cpp", std::nullopt); + EXPECT_TRUE(Inner.setCompileCommand("A.cpp", tooling::CompileCommand())); + EXPECT_TRUE(Outer.setCompileCommand("B.cpp", tooling::CompileCommand())); + EXPECT_TRUE(Inner.setCompileCommand("A.cpp", std::nullopt)); + EXPECT_TRUE(Outer.setCompileCommand("C.cpp", std::nullopt)); EXPECT_THAT(Changes, ElementsAre(ElementsAre("A.cpp"), ElementsAre("B.cpp"), ElementsAre("A.cpp"), ElementsAre("C.cpp"))); } @@ -151,7 +153,7 @@ TEST_F(OverlayCDBTest, Adjustments) { tooling::CompileCommand BarCommand; BarCommand.Filename = testPath("bar.cc"); BarCommand.CommandLine = {"clang++", "-DB=1", testPath("bar.cc")}; - CDB.setCompileCommand(testPath("bar.cc"), BarCommand); + EXPECT_TRUE(CDB.setCompileCommand(testPath("bar.cc"), BarCommand)); Cmd = *CDB.getCompileCommand(testPath("bar.cc")); EXPECT_THAT( Cmd.CommandLine, @@ -412,7 +414,7 @@ TEST(GlobalCompilationDatabaseTest, NonCanonicalFilenames) { llvm::SmallString<128> Root(testRoot()); llvm::sys::path::append(Root, "build", "..", "a.cc"); - DB.setCompileCommand(Root.str(), tooling::CompileCommand()); + EXPECT_TRUE(DB.setCompileCommand(Root.str(), tooling::CompileCommand())); EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(testPath("a.cc"))); DiscoveredFiles.clear(); @@ -432,7 +434,7 @@ TEST_F(OverlayCDBTest, GetProjectInfo) { EXPECT_EQ(DB.getProjectInfo(Header)->SourceRoot, testRoot()); // Shouldn't change after an override. - DB.setCompileCommand(File, tooling::CompileCommand()); + EXPECT_TRUE(DB.setCompileCommand(File, tooling::CompileCommand())); EXPECT_EQ(DB.getProjectInfo(File)->SourceRoot, testRoot()); EXPECT_EQ(DB.getProjectInfo(Header)->SourceRoot, testRoot()); } diff --git a/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp index 6a9e90c3bfa70fc55a61e4bafcc83ab20017c59b..d2d2ae9e7bb6103fb6eda9e099d644be60466a24 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp @@ -111,11 +111,17 @@ TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) { template struct Foo { void fo^o(){} }; )cpp"); - // Not available on function templates and specializations, as definition must - // be visible to all translation units. + // Not available on function template specializations and free function + // templates. EXPECT_UNAVAILABLE(R"cpp( - template void fo^o() {}; - template <> void fo^o() {}; + template void fo^o() {} + template <> void fo^o() {} + )cpp"); + + // Not available on member function templates with unnamed template + // parameters. + EXPECT_UNAVAILABLE(R"cpp( + struct Foo { template void ba^r() {} }; )cpp"); // Not available on methods of unnamed classes. @@ -237,7 +243,7 @@ TEST_F(DefineOutlineTest, ApplyTest) { Foo(T z) __attribute__((weak)) ; int bar; };template -Foo::Foo(T z) __attribute__((weak)) : bar(2){} +inline Foo::Foo(T z) __attribute__((weak)) : bar(2){} )cpp", ""}, // Virt specifiers. @@ -390,7 +396,7 @@ Foo::Foo(T z) __attribute__((weak)) : bar(2){} }; };template template -typename O1::template O2::E O1::template O2::I::foo(T, U..., V, E) { return E1; } +inline typename O1::template O2::E O1::template O2::I::foo(T, U..., V, E) { return E1; } )cpp", ""}, // Destructors @@ -399,6 +405,37 @@ typename O1::template O2::E O1::template O2::I::fo "class A { ~A(); };", "A::~A(){} ", }, + + // Member template + { + R"cpp( + struct Foo { + template + T ^bar() { return {}; } + };)cpp", + R"cpp( + struct Foo { + template + T bar() ; + };template +inline T Foo::bar() { return {}; } +)cpp", + ""}, + + // Class template with member template + { + R"cpp( + template struct Foo { + template T ^bar(const T& t, const U& u) { return {}; } + };)cpp", + R"cpp( + template struct Foo { + template T bar(const T& t, const U& u) ; + };template +template +inline T Foo::bar(const T& t, const U& u) { return {}; } +)cpp", + ""}, }; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Test); diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp index dec63d454d52c6f71e911f4215cd9d8bf9280967..eff4d0f43595c57a9060070aa2836a96535015d1 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/ExtractFunctionTests.cpp @@ -190,6 +190,18 @@ F (extracted();) }]] )cpp"; EXPECT_EQ(apply(CompoundFailInput), "unavailable"); + + ExtraArgs.push_back("-std=c++14"); + // FIXME: Expressions are currently not extracted + EXPECT_EQ(apply(R"cpp( + void call() { [[1+1]]; } + )cpp"), + "unavailable"); + // FIXME: Single expression statements are currently not extracted + EXPECT_EQ(apply(R"cpp( + void call() { [[1+1;]] } + )cpp"), + "unavailable"); } TEST_F(ExtractFunctionTest, DifferentHeaderSourceTest) { @@ -571,6 +583,53 @@ int getNum(bool Superstitious, int Min, int Max) { EXPECT_EQ(apply(Before), After); } +TEST_F(ExtractFunctionTest, OverloadedOperators) { + Context = File; + std::string Before = R"cpp(struct A { + int operator+(int x) { return x; } + }; + A &operator<<(A &, int); + A &operator|(A &, int); + + A stream{}; + + void foo(int, int); + + int main() { + [[foo(1, 2); + foo(3, 4); + stream << 42; + stream + 42; + stream | 42; + foo(1, 2); + foo(3, 4);]] + })cpp"; + std::string After = + R"cpp(struct A { + int operator+(int x) { return x; } + }; + A &operator<<(A &, int); + A &operator|(A &, int); + + A stream{}; + + void foo(int, int); + + void extracted() { +foo(1, 2); + foo(3, 4); + stream << 42; + stream + 42; + stream | 42; + foo(1, 2); + foo(3, 4); +} +int main() { + extracted(); + })cpp"; + EXPECT_EQ(apply(Before), After); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index db971f08ca3dbc1bfdc16940364a5594ed8a71f5..f967dfabd1c9401bdc3ac53fea63ef3701084b19 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -78,6 +78,9 @@ Code actions - Added `Swap operands` tweak for certain binary operators. +- Improved the extract-to-function code action to allow extracting statements + with overloaded operators like ``<<`` of ``std::ostream``. + Signature help ^^^^^^^^^^^^^^ @@ -191,6 +194,11 @@ Changes in existing checks ` check to allow specifying additional functions to match. +- Improved :doc:`bugprone-use-after-move + ` to avoid triggering on + ``reset()`` calls on moved-from ``std::optional`` and ``std::any`` objects, + similarly to smart pointers. + - Improved :doc:`cert-flp30-c ` check to fix false positive that floating point variable is only used in increment expression. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst index 08bb5374bab1f4e74d4608009728229c9a06174f..965fc2d3c29e2462b3b8164fd620f9249e492b1a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst @@ -196,11 +196,13 @@ Any occurrence of the moved variable that is not a reinitialization (see below) is considered to be a use. An exception to this are objects of type ``std::unique_ptr``, -``std::shared_ptr`` and ``std::weak_ptr``, which have defined move behavior -(objects of these classes are guaranteed to be empty after they have been moved -from). Therefore, an object of these classes will only be considered to be used -if it is dereferenced, i.e. if ``operator*``, ``operator->`` or ``operator[]`` -(in the case of ``std::unique_ptr``) is called on it. +``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``. +An exception to this are objects of type ``std::unique_ptr``, +``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``, which +can be reinitialized via ``reset``. For smart pointers specifically, the +moved-from objects have a well-defined state of being ``nullptr``s, and only +``operator*``, ``operator->`` and ``operator[]`` are considered bad accesses as +they would be dereferencing a ``nullptr``. If multiple uses occur after a move, only the first of these is flagged. @@ -222,7 +224,8 @@ The check considers a variable to be reinitialized in the following cases: ``unordered_multimap``. - ``reset()`` is called on the variable and the variable is of type - ``std::unique_ptr``, ``std::shared_ptr`` or ``std::weak_ptr``. + ``std::unique_ptr``, ``std::shared_ptr``, ``std::weak_ptr``, + ``std::optional``, or ``std::any``. - A member function marked with the ``[[clang::reinitializes]]`` attribute is called on the variable. diff --git a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp index b5a7b9720903ebe748bae800332726237dc6b1e9..b1bbb2eb82414cb9890a1cccd0aa174ab65c7214 100644 --- a/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/RecordTest.cpp @@ -609,15 +609,6 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) { )cpp"; Inputs.ExtraFiles["foo.h"] = ""; - auto Clang = std::make_unique( - std::make_shared()); - Clang->createDiagnostics(); - - Clang->setInvocation(std::make_unique()); - ASSERT_TRUE(CompilerInvocation::CreateFromArgs( - Clang->getInvocation(), {Filename.data()}, Clang->getDiagnostics(), - "clang")); - // Create unnamed memory buffers for all the files. auto VFS = llvm::makeIntrusiveRefCnt(); VFS->addFile(Filename, /*ModificationTime=*/0, @@ -626,6 +617,16 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) { VFS->addFile(Extra.getKey(), /*ModificationTime=*/0, llvm::MemoryBuffer::getMemBufferCopy(Extra.getValue(), /*BufferName=*/"")); + + auto Clang = std::make_unique( + std::make_shared()); + Clang->createDiagnostics(*VFS); + + Clang->setInvocation(std::make_unique()); + ASSERT_TRUE(CompilerInvocation::CreateFromArgs( + Clang->getInvocation(), {Filename.data()}, Clang->getDiagnostics(), + "clang")); + auto *FM = Clang->createFileManager(VFS); ASSERT_TRUE(Clang->ExecuteAction(*Inputs.MakeAction())); EXPECT_THAT( diff --git a/clang-tools-extra/test/CMakeLists.txt b/clang-tools-extra/test/CMakeLists.txt index d72a117166a08be689009d93a499d10ae7033fa7..7e4d99d8cfc1d3951d3bcba23bd34f17b1d223d5 100644 --- a/clang-tools-extra/test/CMakeLists.txt +++ b/clang-tools-extra/test/CMakeLists.txt @@ -50,8 +50,6 @@ set(CLANG_TOOLS_TEST_DEPS clang-resource-headers clang-tidy - # Clang-tidy tests need clang for building modules. - clang ) # Add lit test dependencies. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp index 6a4e3990e36dc5afc22b6958f89bdabda6e0a2c6..87dfec4f68061f2160cace37e600ee8379b67a7c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp @@ -33,6 +33,19 @@ struct weak_ptr { bool expired() const; }; +template +struct optional { + optional(); + T& operator*(); + const T& operator*() const; + void reset(); +}; + +struct any { + any(); + void reset(); +}; + template struct pair {}; @@ -257,6 +270,14 @@ void standardSmartPtr() { // CHECK-NOTES: [[@LINE-1]]:5: warning: 'ptr' used after it was moved // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here } + { + std::optional opt; + std::move(opt); + A val = *opt; + (void)val; + // CHECK-NOTES: [[@LINE-2]]:14: warning: 'opt' used after it was moved + // CHECK-NOTES: [[@LINE-4]]:5: note: move occurred here + } { // std::weak_ptr<> cannot be dereferenced directly, so we only check that // member functions may be called on it after a move. @@ -994,10 +1015,10 @@ void standardContainerAssignIsReinit() { } } -// Resetting the standard smart pointer types using reset() is treated as a +// Resetting the standard smart owning types using reset() is treated as a // re-initialization. (We don't test std::weak_ptr<> because it can't be // dereferenced directly.) -void standardSmartPointerResetIsReinit() { +void resetIsReinit() { { std::unique_ptr ptr; std::move(ptr); @@ -1010,6 +1031,20 @@ void standardSmartPointerResetIsReinit() { ptr.reset(new A); *ptr; } + { + std::optional opt; + std::move(opt); + opt.reset(); + std::optional opt2 = opt; + (void)opt2; + } + { + std::any a; + std::move(a); + a.reset(); + std::any a2 = a; + (void)a2; + } } void reinitAnnotation() { diff --git a/clang/Maintainers.rst b/clang/Maintainers.rst index 26495f3d8779452b54ef23101a01a4ea70c91b58..b601f4da0b3a933d1365057e8dbec2e4cccad30f 100644 --- a/clang/Maintainers.rst +++ b/clang/Maintainers.rst @@ -134,6 +134,8 @@ Clang static analyzer | Gábor Horváth | xazax.hun\@gmail.com (email), xazax.hun (Phabricator), Xazax-hun (GitHub) +| Balázs Benics +| benicsbalazs\@gmail.com (email), steakhal (Phabricator), steakhal (GitHub) Compiler options ~~~~~~~~~~~~~~~~ @@ -168,6 +170,12 @@ Constant Expressions | mariya.podchishchaeva\@intel.com (email), Fznamznon (GitHub), fznamznon (Discord), Fznamznon (Discourse) +Thread Safety Analysis +~~~~~~~~~~~~~~~~~~~~~~ +| Aaron Puchert +| aaron.puchert\@sap.com (email), aaronpuchert (GitHub), aaronpuchert (Discourse) + + Tools ----- These maintainers are responsible for user-facing tools under the Clang diff --git a/clang/cmake/caches/CrossWinToARMLinux.cmake b/clang/cmake/caches/CrossWinToARMLinux.cmake index 87118bbd33377d37b01701995052562c6b9ddedd..853217c6db61a30bbde97b3f7f17aa3f384598ec 100644 --- a/clang/cmake/caches/CrossWinToARMLinux.cmake +++ b/clang/cmake/caches/CrossWinToARMLinux.cmake @@ -119,7 +119,6 @@ if (NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") endif() -set(CMAKE_CROSSCOMPILING ON CACHE BOOL "") set(CMAKE_CL_SHOWINCLUDES_PREFIX "Note: including file: " CACHE STRING "") # Required if COMPILER_RT_DEFAULT_TARGET_ONLY is ON set(CMAKE_C_COMPILER_TARGET "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "") @@ -219,6 +218,11 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_CXX_ABI set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "") # Merge libc++ and libc++abi libraries into the single libc++ library file. set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "") +# Forcely disable the libc++ benchmarks on Windows build hosts +# (current benchmark test configuration does not support the cross builds there). +if (WIN32) + set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_INCLUDE_BENCHMARKS OFF CACHE BOOL "") +endif(WIN32) # Avoid searching for the python3 interpreter during the runtimes configuration for the cross builds. # It starts searching the python3 package using the target's sysroot path, that usually is not compatible with the build host. diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 5af98c7b3b3fba237702559ca6db8582a2b8b12e..747d9974828984a1d6aff6b190a96217ae5dd9cc 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -302,7 +302,7 @@ if(FUCHSIA_SDK) set(LLVM_RUNTIME_MULTILIB_hwasan+noexcept_TARGETS "aarch64-unknown-fuchsia;riscv64-unknown-fuchsia" CACHE STRING "") endif() -foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi) +foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi;armv8.1m.main-none-eabi) list(APPEND BUILTIN_TARGETS "${target}") set(BUILTINS_${target}_CMAKE_SYSTEM_NAME Generic CACHE STRING "") set(BUILTINS_${target}_CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "") @@ -313,6 +313,9 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi) if(${target} STREQUAL "armv8m.main-none-eabi") set(BUILTINS_${target}_CMAKE_${lang}_local_flags "${BUILTINS_${target}_CMAKE_${lang}_local_flags} -mfloat-abi=softfp -march=armv8m.main+fp+dsp -mcpu=cortex-m33" CACHE STRING "") endif() + if(${target} STREQUAL "armv8.1m.main-none-eabi") + set(BUILTINS_${target}_CMAKE_${lang}_local_flags "${BUILTINS_${target}_CMAKE_${lang}_local_flags} -mfloat-abi=hard -march=armv8.1-m.main+mve.fp+fp.dp -mcpu=cortex-m55" CACHE STRING "") + endif() set(BUILTINS_${target}_CMAKE_${lang}_FLAGS "${BUILTINS_${target}_CMAKE_${lang}_local_flags}" CACHE STRING "") endforeach() foreach(type SHARED;MODULE;EXE) @@ -333,6 +336,9 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi) if(${target} STREQUAL "armv8m.main-none-eabi") set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mfloat-abi=softfp -march=armv8m.main+fp+dsp -mcpu=cortex-m33" CACHE STRING "") endif() + if(${target} STREQUAL "armv8.1m.main-none-eabi") + set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mfloat-abi=hard -march=armv8.1-m.main+mve.fp+fp.dp -mcpu=cortex-m55" CACHE STRING "") + endif() set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "${RUNTIMES_${target}_CMAKE_${lang}_local_flags}" CACHE STRING "") endforeach() foreach(type SHARED;MODULE;EXE) diff --git a/clang/docs/AddressSanitizer.rst b/clang/docs/AddressSanitizer.rst index d937cbfdf583c4b377c6e8be91997104fdda5874..8d9295f246f0d35e1f225b305ded83a6c10b24d2 100644 --- a/clang/docs/AddressSanitizer.rst +++ b/clang/docs/AddressSanitizer.rst @@ -326,15 +326,13 @@ Supported Platforms AddressSanitizer is supported on: -* Linux i386/x86\_64 (tested on Ubuntu 12.04) -* macOS 10.7 - 10.11 (i386/x86\_64) +* Linux +* macOS * iOS Simulator -* Android ARM -* NetBSD i386/x86\_64 -* FreeBSD i386/x86\_64 (tested on FreeBSD 11-current) -* Windows 8.1+ (i386/x86\_64) - -Ports to various other platforms are in progress. +* Android +* NetBSD +* FreeBSD +* Windows 8.1+ Current Status ============== diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index b70ec35f3da229c4960b2055f96662e99a8825ca..39d389b816f12944bfe2fc931791d707e0e920ed 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -160,6 +160,10 @@ wording a diagnostic. named in a diagnostic message. e.g., prefer wording like ``'this' pointer cannot be null in well-defined C++ code`` over wording like ``this pointer cannot be null in well-defined C++ code``. +* Prefer diagnostic wording without contractions whenever possible. The single + quote in a contraction can be visually distracting due to its use with + syntactic constructs and contractions can be harder to understand for non- + native English speakers. The Format String ^^^^^^^^^^^^^^^^^ @@ -315,6 +319,17 @@ Description: than ``1`` are not supported. This formatter is currently hard-coded to use English ordinals. +**"human" format** + +Example: + ``"total size is %human0 bytes"`` +Class: + Integers +Description: + This is a formatter which represents the argument number in a human readable + format: the value ``123`` stays ``123``, ``12345`` becomes ``12.34k``, + ``6666666` becomes ``6.67M``, and so on for 'G' and 'T'. + **"objcclass" format** Example: diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 0998e6b30e229e0a6036b67c8902857106dadb16..ff8e841ee53a2bdb5af1c526b371b56614264de8 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -745,12 +745,10 @@ Let ``VT`` be a vector type and ``ET`` the element type of ``VT``. ======================================= ====================================================================== ================================== Name Operation Supported element types ======================================= ====================================================================== ================================== - ET __builtin_reduce_max(VT a) return x or y, whichever is larger; If exactly one argument is integer and floating point types - a NaN, return the other argument. If both arguments are NaNs, - fmax() return a NaN. - ET __builtin_reduce_min(VT a) return x or y, whichever is smaller; If exactly one argument integer and floating point types - is a NaN, return the other argument. If both arguments are - NaNs, fmax() return a NaN. + ET __builtin_reduce_max(VT a) return the largest element of the vector. The floating point result integer and floating point types + will always be a number unless all elements of the vector are NaN. + ET __builtin_reduce_min(VT a) return the smallest element of the vector. The floating point result integer and floating point types + will always be a number unless all elements of the vector are NaN. ET __builtin_reduce_add(VT a) \+ integer types ET __builtin_reduce_mul(VT a) \* integer types ET __builtin_reduce_and(VT a) & integer types diff --git a/clang/docs/LeakSanitizer.rst b/clang/docs/LeakSanitizer.rst index adcb6421c6a1f92dd0062c4664ad95c80dd3d425..ecdb87f0b259dd970916ce434feab2de9f2b2207 100644 --- a/clang/docs/LeakSanitizer.rst +++ b/clang/docs/LeakSanitizer.rst @@ -54,11 +54,11 @@ constraints in mind and may compromise the security of the resulting executable. Supported Platforms =================== -* Android aarch64/i386/x86_64 -* Fuchsia aarch64/x86_64 -* Linux arm/aarch64/mips64/ppc64/ppc64le/riscv64/s390x/i386/x86\_64 -* macOS aarch64/i386/x86\_64 -* NetBSD i386/x86_64 +* Android +* Fuchsia +* Linux +* macOS +* NetBSD More Information ================ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7c210c17dda7d4666e88c24f4bbdcab7b272d21e..49464e457da68196af9378f4e5bcefab6c3f12c2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -271,6 +271,8 @@ Resolutions to C++ Defect Reports C Language Changes ------------------ +- Extend clang's ```` to define ``LONG_LONG_*`` macros for Android's bionic. + C2y Feature Support ^^^^^^^^^^^^^^^^^^^ @@ -278,7 +280,7 @@ C2y Feature Support which adds the ``i`` and ``j`` suffixes for the creation of a ``_Complex`` constant value. Clang has always supported these suffixes as a GNU extension, so ``-Wgnu-imaginary-constant`` no longer has effect in C modes, as this is - not a C2y extension in C. ``-Wgnu-imaginary-constant`` still applies in C++ + now a C2y extension in C. ``-Wgnu-imaginary-constant`` still applies in C++ modes. - Clang updated conformance for `N3370 `_ @@ -318,6 +320,7 @@ C23 Feature Support ^^^^^^^^^^^^^^^^^^^ - Clang now supports `N3029 `_ Improved Normal Enumerations. +- Clang now officially supports `N3030 `_ Enhancements to Enumerations. Clang already supported it as an extension, so there were no changes to compiler behavior. Non-comprehensive list of changes in this release ------------------------------------------------- @@ -352,6 +355,10 @@ Non-comprehensive list of changes in this release The flexible array member (FAM) can now be accessed immediately without causing issues with the sanitizer because the counter is automatically set. +- ``__builtin_reduce_add`` function can now be used in constant expressions. +- ``__builtin_reduce_mul`` function can now be used in constant expressions. +- ``__builtin_reduce_and`` function can now be used in constant expressions. + New Compiler Flags ------------------ @@ -449,6 +456,9 @@ Attribute Changes in Clang - Fix a bug where clang doesn't automatically apply the ``[[gsl::Owner]]`` or ``[[gsl::Pointer]]`` to STL explicit template specialization decls. (#GH109442) +- Clang now supports ``[[clang::lifetime_capture_by(X)]]``. Similar to lifetimebound, this can be + used to specify when a reference to a function parameter is captured by another capturing entity ``X``. + Improvements to Clang's diagnostics ----------------------------------- @@ -527,6 +537,33 @@ Improvements to Clang's diagnostics - Clang now diagnoses ``[[deprecated]]`` attribute usage on local variables (#GH90073). +- Improved diagnostic message for ``__builtin_bit_cast`` size mismatch (#GH115870). + +- Clang now omits shadow warnings for enum constants in separate class scopes (#GH62588). + +- When diagnosing an unused return value of a type declared ``[[nodiscard]]``, the type + itself is now included in the diagnostic. + +- Clang will now prefer the ``[[nodiscard]]`` declaration on function declarations over ``[[nodiscard]]`` + declaration on the return type of a function. Previously, when both have a ``[[nodiscard]]`` declaration attached, + the one on the return type would be preferred. This may affect the generated warning message: + + .. code-block:: c++ + + struct [[nodiscard("Reason 1")]] S {}; + [[nodiscard("Reason 2")]] S getS(); + void use() + { + getS(); // Now diagnoses "Reason 2", previously diagnoses "Reason 1" + } + +- Clang now diagnoses ``= delete("reason")`` extension warnings only in pedantic mode rather than on by default. (#GH109311). + +- Clang now diagnoses missing return value in functions containing ``if consteval`` (#GH116485). + +- Clang now correctly recognises code after a call to a ``[[noreturn]]`` constructor + as unreachable (#GH63009). + Improvements to Clang's time-trace ---------------------------------- @@ -547,6 +584,8 @@ Bug Fixes in This Version the unsupported type instead of the ``register`` keyword (#GH109776). - Fixed a crash when emit ctor for global variant with flexible array init (#GH113187). - Fixed a crash when GNU statement expression contains invalid statement (#GH113468). +- Fixed a failed assertion when using ``__attribute__((noderef))`` on an + ``_Atomic``-qualified type (#GH116124). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -654,6 +693,8 @@ Bug Fixes to C++ Support - Name independent data members were not correctly initialized from default member initializers. (#GH114069) - Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the assumption if they also occur inside of a dependent lambda. (#GH114787) +- Clang now uses valid deduced type locations when diagnosing functions with trailing return type + missing placeholder return type. (#GH78694) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -661,6 +702,8 @@ Bug Fixes to AST Handling - Fixed a crash that occurred when dividing by zero in complex integer division. (#GH55390). - Fixed a bug in ``ASTContext::getRawCommentForAnyRedecl()`` where the function could sometimes incorrectly return null even if a comment was present. (#GH108145) +- Clang now correctly parses the argument of the ``relates``, ``related``, ``relatesalso``, + and ``relatedalso`` comment commands. Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ @@ -698,6 +741,19 @@ Target Specific Changes AMDGPU Support ^^^^^^^^^^^^^^ +- Initial support for gfx950 + +- Added headers ``gpuintrin.h`` and ``amdgpuintrin.h`` that contains common + definitions for GPU builtin functions. This header can be included for OpenMP, + CUDA, HIP, OpenCL, and C/C++. + +NVPTX Support +^^^^^^^^^^^^^^ + +- Added headers ``gpuintrin.h`` and ``nvptxintrin.h`` that contains common + definitions for GPU builtin functions. This header can be included for OpenMP, + CUDA, HIP, OpenCL, and C/C++. + X86 Support ^^^^^^^^^^^ @@ -744,6 +800,9 @@ X86 Support - Support ISA of ``AMX-MOVRS``. - Support ISA of ``AMX-AVX512``. - Support ISA of ``AMX-TF32``. +- Support ISA of ``MOVRS``. + +- Supported ``-march/tune=diamondrapids`` Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/docs/ThreadSafetyAnalysis.rst b/clang/docs/ThreadSafetyAnalysis.rst index cc4089b97b4923e6a8c17148b0f47d47d1639db8..f6517afc3bfc2a9182b15ac656bfb9d7735acf34 100644 --- a/clang/docs/ThreadSafetyAnalysis.rst +++ b/clang/docs/ThreadSafetyAnalysis.rst @@ -933,11 +933,25 @@ implementation. MutexLocker(Mutex *mu, defer_lock_t) EXCLUDES(mu) : mut(mu), locked(false) {} // Same as constructors, but without tag types. (Requires C++17 copy elision.) - static MutexLocker Lock(Mutex *mu) ACQUIRE(mu); - static MutexLocker Adopt(Mutex *mu) REQUIRES(mu); - static MutexLocker ReaderLock(Mutex *mu) ACQUIRE_SHARED(mu); - static MutexLocker AdoptReaderLock(Mutex *mu) REQUIRES_SHARED(mu); - static MutexLocker DeferLock(Mutex *mu) EXCLUDES(mu); + static MutexLocker Lock(Mutex *mu) ACQUIRE(mu) { + return MutexLocker(mu); + } + + static MutexLocker Adopt(Mutex *mu) REQUIRES(mu) { + return MutexLocker(mu, adopt_lock); + } + + static MutexLocker ReaderLock(Mutex *mu) ACQUIRE_SHARED(mu) { + return MutexLocker(mu, shared_lock); + } + + static MutexLocker AdoptReaderLock(Mutex *mu) REQUIRES_SHARED(mu) { + return MutexLocker(mu, adopt_lock, shared_lock); + } + + static MutexLocker DeferLock(Mutex *mu) EXCLUDES(mu) { + return MutexLocker(mu, defer_lock); + } // Release *this and all associated mutexes, if they are still held. // There is no warning if the scope was already unlocked before. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 2ac840662f1dbb2a5802f82822c2cb49c253cca4..5c2b04145e6cd80f533699f7546e6adc96062610 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1324,9 +1324,9 @@ disabling all warnings wins. Controlling Diagnostics via Suppression Mappings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Warning suppression mappings enable users to suppress Clang's diagnostics in a -per-file granular manner. Enabling enforcement of diagnostics in specific parts -of the project, even if there are violations in some headers. +Warning suppression mappings enable users to suppress Clang's diagnostics at a +per-file granularity. This allows enforcing diagnostics in specific parts of the +project even if there are violations in some headers. .. code-block:: console diff --git a/clang/docs/WarningSuppressionMappings.rst b/clang/docs/WarningSuppressionMappings.rst index 54f8697acf67931403fc99aa275c635bec21e536..d96341ac6e563bcf2508e9dd5dff3353917ac10e 100644 --- a/clang/docs/WarningSuppressionMappings.rst +++ b/clang/docs/WarningSuppressionMappings.rst @@ -8,19 +8,19 @@ Warning suppression mappings Introduction ============ -Warning suppression mappings enable users to suppress Clang's diagnostics in a -per-file granular manner. Enabling enforcement of diagnostics in specific parts -of the project, even if there are violations in some headers. +Warning suppression mappings enable users to suppress Clang's diagnostics at a +per-file granularity. This allows enforcing diagnostics in specific parts of the +project even if there are violations in some headers. Goal and usage ============== Clang allows diagnostics to be configured at a translation-unit granularity. If a ``foo.cpp`` is compiled with ``-Wfoo``, all transitively included headers -also need to be clean. Hence turning on new warnings in large codebases requires -cleaning up all the existing warnings. This might not be possible when some -dependencies aren't in the project owner's control or because new violations are -creeping up quicker than the clean up. +also need to be clean. Hence, turning on new warnings in large codebases +requires cleaning up all the existing warnings. This might not be possible when +some dependencies aren't in the project owner's control or because new +violations are creeping up quicker than the clean up. Warning suppression mappings aim to alleviate some of these concerns by making diagnostic configuration granularity finer, at a source file level. diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 45e37b08f6ceab8c3fd4f5a8a0dee2aa04a66d45..2e72d239a714a5ad27a603ba81b9d30225766f4e 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2198,7 +2198,9 @@ enum CXCursorKind { */ CXCursor_OpenACCLoopConstruct = 321, - CXCursor_LastStmt = CXCursor_OpenACCLoopConstruct, + CXCursor_OpenACCCombinedConstruct = 322, + + CXCursor_LastStmt = CXCursor_OpenACCCombinedConstruct, /** * Cursor that represents the translation unit itself. diff --git a/clang/include/clang/APINotes/Types.h b/clang/include/clang/APINotes/Types.h index 6ad1c8507011463e7878fe92b6eb50b6c272bf68..ff374ad3ada065a141c828077e5328dedd95ccc5 100644 --- a/clang/include/clang/APINotes/Types.h +++ b/clang/include/clang/APINotes/Types.h @@ -724,6 +724,11 @@ class TagInfo : public CommonTypeInfo { LLVM_PREFERRED_TYPE(bool) unsigned SwiftCopyable : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftEscapableSpecified : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned SwiftEscapable : 1; + public: std::optional SwiftImportAs; std::optional SwiftRetainOp; @@ -736,7 +741,8 @@ public: TagInfo() : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false), - SwiftCopyable(false) {} + SwiftCopyable(false), SwiftEscapableSpecified(false), + SwiftEscapable(false) {} std::optional isFlagEnum() const { if (HasFlagEnum) @@ -757,6 +763,16 @@ public: SwiftCopyable = Value.value_or(false); } + std::optional isSwiftEscapable() const { + return SwiftEscapableSpecified ? std::optional(SwiftEscapable) + : std::nullopt; + } + + void setSwiftEscapable(std::optional Value) { + SwiftEscapableSpecified = Value.has_value(); + SwiftEscapable = Value.value_or(false); + } + TagInfo &operator|=(const TagInfo &RHS) { static_cast(*this) |= RHS; @@ -779,6 +795,9 @@ public: if (!SwiftCopyableSpecified) setSwiftCopyable(RHS.isSwiftCopyable()); + if (!SwiftEscapableSpecified) + setSwiftEscapable(RHS.isSwiftEscapable()); + return *this; } @@ -795,6 +814,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { LHS.SwiftConformance == RHS.SwiftConformance && LHS.isFlagEnum() == RHS.isFlagEnum() && LHS.isSwiftCopyable() == RHS.isSwiftCopyable() && + LHS.isSwiftEscapable() == RHS.isSwiftEscapable() && LHS.EnumExtensibility == RHS.EnumExtensibility; } diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index 088a2bd0fdd407b8aba6ec10c31b0dd5217740ad..8c3fa842ab8b9d997e98a77133be7cc69b66ff42 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -62,7 +62,8 @@ class TypeSourceInfo; class ASTImporter { friend class ASTNodeImporter; public: - using NonEquivalentDeclSet = llvm::DenseSet>; + using NonEquivalentDeclSet = + llvm::DenseSet>; using ImportedCXXBaseSpecifierMap = llvm::DenseMap; diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index a443a88bab1f2d2b07f0447e60a847b528060784..3d63d581a9be6033f661c959fa3347db5c5f45e7 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -800,6 +800,13 @@ public: Visit(A); } + void VisitLabelStmt(const LabelStmt *Node) { + if (Node->getDecl()->hasAttrs()) { + for (const auto *A : Node->getDecl()->getAttrs()) + Visit(A); + } + } + void VisitCXXCatchStmt(const CXXCatchStmt *Node) { Visit(Node->getExceptionDecl()); } diff --git a/clang/include/clang/AST/ASTStructuralEquivalence.h b/clang/include/clang/AST/ASTStructuralEquivalence.h index 029439c8e9a3ac334e91ea2cb9e246641435c971..67aa0023c25d0857e1fc983a41dd7ad31ace5a61 100644 --- a/clang/include/clang/AST/ASTStructuralEquivalence.h +++ b/clang/include/clang/AST/ASTStructuralEquivalence.h @@ -39,6 +39,10 @@ enum class StructuralEquivalenceKind { }; struct StructuralEquivalenceContext { + /// Store declaration pairs already found to be non-equivalent. + /// key: (from, to, IgnoreTemplateParmDepth) + using NonEquivalentDeclSet = llvm::DenseSet>; + /// AST contexts for which we are checking structural equivalence. ASTContext &FromCtx, &ToCtx; @@ -52,7 +56,7 @@ struct StructuralEquivalenceContext { /// Declaration (from, to) pairs that are known not to be equivalent /// (which we have already complained about). - llvm::DenseSet> &NonEquivalentDecls; + NonEquivalentDeclSet &NonEquivalentDecls; StructuralEquivalenceKind EqKind; @@ -72,12 +76,13 @@ struct StructuralEquivalenceContext { /// Whether to ignore comparing the depth of template param(TemplateTypeParm) bool IgnoreTemplateParmDepth; - StructuralEquivalenceContext( - ASTContext &FromCtx, ASTContext &ToCtx, - llvm::DenseSet> &NonEquivalentDecls, - StructuralEquivalenceKind EqKind, bool StrictTypeSpelling = false, - bool Complain = true, bool ErrorOnTagTypeMismatch = false, - bool IgnoreTemplateParmDepth = false) + StructuralEquivalenceContext(ASTContext &FromCtx, ASTContext &ToCtx, + NonEquivalentDeclSet &NonEquivalentDecls, + StructuralEquivalenceKind EqKind, + bool StrictTypeSpelling = false, + bool Complain = true, + bool ErrorOnTagTypeMismatch = false, + bool IgnoreTemplateParmDepth = false) : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls), EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling), ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain), diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index 6102eb017935309bf6282e5889d92634ced1e9ec..6699284d215bd00d3107de527346d89caf61763e 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -30,6 +30,7 @@ namespace clang { template class CanProxy; template struct CanProxyAdaptor; +class ASTContext; class CXXRecordDecl; class EnumDecl; class Expr; @@ -164,14 +165,14 @@ public: /// Determines whether this canonical type is more qualified than /// the @p Other canonical type. - bool isMoreQualifiedThan(CanQual Other) const { - return Stored.isMoreQualifiedThan(Other.Stored); + bool isMoreQualifiedThan(CanQual Other, const ASTContext &Ctx) const { + return Stored.isMoreQualifiedThan(Other.Stored, Ctx); } /// Determines whether this canonical type is at least as qualified as /// the @p Other canonical type. - bool isAtLeastAsQualifiedAs(CanQual Other) const { - return Stored.isAtLeastAsQualifiedAs(Other.Stored); + bool isAtLeastAsQualifiedAs(CanQual Other, const ASTContext &Ctx) const { + return Stored.isAtLeastAsQualifiedAs(Other.Stored, Ctx); } /// If the canonical type is a reference type, returns the type that diff --git a/clang/include/clang/AST/CommentCommands.td b/clang/include/clang/AST/CommentCommands.td index a410cd4039bee1e591aa692a27711be0184eab1b..f6dd67dc2590f0e775b87b9ba27dd4519db85a65 100644 --- a/clang/include/clang/AST/CommentCommands.td +++ b/clang/include/clang/AST/CommentCommands.td @@ -111,6 +111,11 @@ def Extends : InlineCommand<"extends">; def Implements : InlineCommand<"implements">; def MemberOf : InlineCommand<"memberof">; +def Relates : InlineCommand<"relates">; +def Related : InlineCommand<"related">; +def RelatesAlso : InlineCommand<"relatesalso">; +def RelatedAlso : InlineCommand<"relatedalso">; + //===----------------------------------------------------------------------===// // BlockCommand //===----------------------------------------------------------------------===// @@ -248,11 +253,6 @@ def Page : VerbatimLineCommand<"page">; def Mainpage : VerbatimLineCommand<"mainpage">; def Subpage : VerbatimLineCommand<"subpage">; -def Relates : VerbatimLineCommand<"relates">; -def Related : VerbatimLineCommand<"related">; -def RelatesAlso : VerbatimLineCommand<"relatesalso">; -def RelatedAlso : VerbatimLineCommand<"relatedalso">; - def AddIndex : VerbatimLineCommand<"addindex">; // These take a single argument mostly, but since they include a file they'll diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 466c65a9685ad32cf96905591f01bb8a728344f3..708c8656decbe017b7d678f29b6bfeeabf4f4373 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -3181,12 +3181,14 @@ public: QualType getCallReturnType(const ASTContext &Ctx) const; /// Returns the WarnUnusedResultAttr that is either declared on the called - /// function, or its return type declaration. - const Attr *getUnusedResultAttr(const ASTContext &Ctx) const; + /// function, or its return type declaration, together with a NamedDecl that + /// refers to the declaration the attribute is attached onto. + std::pair + getUnusedResultAttr(const ASTContext &Ctx) const; /// Returns true if this call expression should warn on unused results. bool hasUnusedResultAttr(const ASTContext &Ctx) const { - return getUnusedResultAttr(Ctx) != nullptr; + return getUnusedResultAttr(Ctx).second != nullptr; } SourceLocation getRParenLoc() const { return RParenLoc; } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 73f3b16eec86327c1c8013dd7325a050fedff9ca..7aac857a3ef7a25a3797917722c23fe48e730bf3 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -4106,15 +4106,6 @@ bool RecursiveASTVisitor::VisitOpenACCClauseList( for (const auto *C : Clauses) TRY_TO(VisitOpenACCClause(C)); -// if (const auto *WithCond = dyn_cast(C); -// WithCond && WIthCond->hasConditionExpr()) { -// TRY_TO(TraverseStmt(WithCond->getConditionExpr()); -// } else if (const auto * -// } -// OpenACCClauseWithCondition::getConditionExpr/hasConditionExpr -//OpenACCClauseWithExprs::children (might be null?) - // TODO OpenACC: When we have Clauses with expressions, we should visit them - // here. return true; } @@ -4129,6 +4120,8 @@ DEF_TRAVERSE_STMT(OpenACCComputeConstruct, { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) DEF_TRAVERSE_STMT(OpenACCLoopConstruct, { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) +DEF_TRAVERSE_STMT(OpenACCCombinedConstruct, + { TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); }) // Traverse HLSL: Out argument expression DEF_TRAVERSE_STMT(HLSLOutArgExpr, {}) diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h index 3eb50f9353ed19b85cbf2a7269618471e7191976..fa8793e740822f588b849471cc50be63c4887e26 100644 --- a/clang/include/clang/AST/StmtOpenACC.h +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -166,11 +166,6 @@ class OpenACCComputeConstruct final } void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } - // Serialization helper function that searches the structured block for 'loop' - // constructs that should be associated with this, and sets their parent - // compute construct to this one. This isn't necessary normally, since we have - // the ability to record the state during parsing. - void findAndSetChildLoops(); public: static bool classof(const Stmt *T) { @@ -204,6 +199,8 @@ class OpenACCLoopConstruct final friend class ASTStmtWriter; friend class ASTStmtReader; friend class ASTContext; + friend class OpenACCAssociatedStmtConstruct; + friend class OpenACCCombinedConstruct; friend class OpenACCComputeConstruct; OpenACCLoopConstruct(unsigned NumClauses); @@ -243,5 +240,57 @@ public: return ParentComputeConstructKind; } }; + +// This class represents a 'combined' construct, which has a bunch of rules +// shared with both loop and compute constructs. +class OpenACCCombinedConstruct final + : public OpenACCAssociatedStmtConstruct, + public llvm::TrailingObjects { + OpenACCCombinedConstruct(unsigned NumClauses) + : OpenACCAssociatedStmtConstruct( + OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid, + SourceLocation{}, SourceLocation{}, SourceLocation{}, + /*AssociatedStmt=*/nullptr) { + std::uninitialized_value_construct( + getTrailingObjects(), + getTrailingObjects() + NumClauses); + setClauseList(MutableArrayRef(getTrailingObjects(), + NumClauses)); + } + + OpenACCCombinedConstruct(OpenACCDirectiveKind K, SourceLocation Start, + SourceLocation DirectiveLoc, SourceLocation End, + ArrayRef Clauses, + Stmt *StructuredBlock) + : OpenACCAssociatedStmtConstruct(OpenACCCombinedConstructClass, K, Start, + DirectiveLoc, End, StructuredBlock) { + assert(isOpenACCCombinedDirectiveKind(K) && + "Only parallel loop, serial loop, and kernels loop constructs " + "should be represented by this type"); + + std::uninitialized_copy(Clauses.begin(), Clauses.end(), + getTrailingObjects()); + setClauseList(MutableArrayRef(getTrailingObjects(), + Clauses.size())); + } + void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } + +public: + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpenACCCombinedConstructClass; + } + + static OpenACCCombinedConstruct *CreateEmpty(const ASTContext &C, + unsigned NumClauses); + static OpenACCCombinedConstruct * + Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, + SourceLocation DirectiveLoc, SourceLocation End, + ArrayRef Clauses, Stmt *StructuredBlock); + Stmt *getLoop() { return getAssociatedStmt(); } + const Stmt *getLoop() const { + return const_cast(this)->getLoop(); + } +}; } // namespace clang #endif // LLVM_CLANG_AST_STMTOPENACC_H diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 9c320c8ae3e54cd12c44389ce4407ea2c2bdaa9e..988b142a7672a30abeb9162be5707485f3a8a626 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -410,6 +410,7 @@ public: void VisitHLSLOutArgExpr(const HLSLOutArgExpr *E); void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S); void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S); + void VisitOpenACCCombinedConstruct(const OpenACCCombinedConstruct *S); void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S); void VisitEmbedExpr(const EmbedExpr *S); void VisitAtomicExpr(const AtomicExpr *AE); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 723127ba5e3fb5b4ce02bfaf9270e587dc5a094a..1c40328c83b68ac0e57e3f19c108388d1a792882 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -323,6 +323,7 @@ public: /// * Objective C: the GC attributes (none, weak, or strong) class Qualifiers { public: + Qualifiers() = default; enum TQ : uint64_t { // NOTE: These flags must be kept in sync with DeclSpec::TQ. Const = 0x1, @@ -697,45 +698,27 @@ public: /// every address space is a superset of itself. /// CL2.0 adds: /// __generic is a superset of any address space except for __constant. - static bool isAddressSpaceSupersetOf(LangAS A, LangAS B) { + static bool isAddressSpaceSupersetOf(LangAS A, LangAS B, + const ASTContext &Ctx) { // Address spaces must match exactly. - return A == B || - // Otherwise in OpenCLC v2.0 s6.5.5: every address space except - // for __constant can be used as __generic. - (A == LangAS::opencl_generic && B != LangAS::opencl_constant) || - // We also define global_device and global_host address spaces, - // to distinguish global pointers allocated on host from pointers - // allocated on device, which are a subset of __global. - (A == LangAS::opencl_global && (B == LangAS::opencl_global_device || - B == LangAS::opencl_global_host)) || - (A == LangAS::sycl_global && (B == LangAS::sycl_global_device || - B == LangAS::sycl_global_host)) || - // Consider pointer size address spaces to be equivalent to default. - ((isPtrSizeAddressSpace(A) || A == LangAS::Default) && - (isPtrSizeAddressSpace(B) || B == LangAS::Default)) || - // Default is a superset of SYCL address spaces. - (A == LangAS::Default && - (B == LangAS::sycl_private || B == LangAS::sycl_local || - B == LangAS::sycl_global || B == LangAS::sycl_global_device || - B == LangAS::sycl_global_host)) || - // In HIP device compilation, any cuda address space is allowed - // to implicitly cast into the default address space. - (A == LangAS::Default && - (B == LangAS::cuda_constant || B == LangAS::cuda_device || - B == LangAS::cuda_shared)); + return A == B || isTargetAddressSpaceSupersetOf(A, B, Ctx); } + static bool isTargetAddressSpaceSupersetOf(LangAS A, LangAS B, + const ASTContext &Ctx); + /// Returns true if the address space in these qualifiers is equal to or /// a superset of the address space in the argument qualifiers. - bool isAddressSpaceSupersetOf(Qualifiers other) const { - return isAddressSpaceSupersetOf(getAddressSpace(), other.getAddressSpace()); + bool isAddressSpaceSupersetOf(Qualifiers other, const ASTContext &Ctx) const { + return isAddressSpaceSupersetOf(getAddressSpace(), other.getAddressSpace(), + Ctx); } /// Determines if these qualifiers compatibly include another set. /// Generally this answers the question of whether an object with the other /// qualifiers can be safely used as an object with these qualifiers. - bool compatiblyIncludes(Qualifiers other) const { - return isAddressSpaceSupersetOf(other) && + bool compatiblyIncludes(Qualifiers other, const ASTContext &Ctx) const { + return isAddressSpaceSupersetOf(other, Ctx) && // ObjC GC qualifiers can match, be added, or be removed, but can't // be changed. (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || @@ -1273,11 +1256,11 @@ public: /// Determine whether this type is more qualified than the other /// given type, requiring exact equality for non-CVR qualifiers. - bool isMoreQualifiedThan(QualType Other) const; + bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const; /// Determine whether this type is at least as qualified as the other /// given type, requiring exact equality for non-CVR qualifiers. - bool isAtLeastAsQualifiedAs(QualType Other) const; + bool isAtLeastAsQualifiedAs(QualType Other, const ASTContext &Ctx) const; QualType getNonReferenceType() const; @@ -1425,11 +1408,12 @@ public: /// address spaces overlap iff they are they same. /// OpenCL C v2.0 s6.5.5 adds: /// __generic overlaps with any address space except for __constant. - bool isAddressSpaceOverlapping(QualType T) const { + bool isAddressSpaceOverlapping(QualType T, const ASTContext &Ctx) const { Qualifiers Q = getQualifiers(); Qualifiers TQ = T.getQualifiers(); // Address spaces overlap if at least one of them is a superset of another - return Q.isAddressSpaceSupersetOf(TQ) || TQ.isAddressSpaceSupersetOf(Q); + return Q.isAddressSpaceSupersetOf(TQ, Ctx) || + TQ.isAddressSpaceSupersetOf(Q, Ctx); } /// Returns gc attribute of this type. @@ -8115,24 +8099,26 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { /// is more qualified than "const int", "volatile int", and /// "int". However, it is not more qualified than "const volatile /// int". -inline bool QualType::isMoreQualifiedThan(QualType other) const { +inline bool QualType::isMoreQualifiedThan(QualType other, + const ASTContext &Ctx) const { Qualifiers MyQuals = getQualifiers(); Qualifiers OtherQuals = other.getQualifiers(); - return (MyQuals != OtherQuals && MyQuals.compatiblyIncludes(OtherQuals)); + return (MyQuals != OtherQuals && MyQuals.compatiblyIncludes(OtherQuals, Ctx)); } /// Determine whether this type is at last /// as qualified as the Other type. For example, "const volatile /// int" is at least as qualified as "const int", "volatile int", /// "int", and "const volatile int". -inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { +inline bool QualType::isAtLeastAsQualifiedAs(QualType other, + const ASTContext &Ctx) const { Qualifiers OtherQuals = other.getQualifiers(); // Ignore __unaligned qualifier if this type is a void. if (getUnqualifiedType()->isVoidType()) OtherQuals.removeUnaligned(); - return getQualifiers().compatiblyIncludes(OtherQuals); + return getQualifiers().compatiblyIncludes(OtherQuals, Ctx); } /// If Type is a reference type (e.g., const diff --git a/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index 2f202607bd3fa993b9654998a961bfee4edf432c..9f365d1a3b6557865221b1ee8dc2fc0a907b204a 100644 --- a/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -1363,11 +1363,7 @@ public: } /// Return the list of basic blocks that this terminator can branch to. - ArrayRef successors(); - - ArrayRef successors() const { - return const_cast(this)->successors(); - } + ArrayRef successors() const; }; /// Jump to another basic block. @@ -1391,7 +1387,7 @@ public: unsigned index() const { return Index; } /// Return the list of basic blocks that this terminator can branch to. - ArrayRef successors() { return TargetBlock; } + ArrayRef successors() const { return TargetBlock; } template typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1439,7 +1435,7 @@ public: BasicBlock *elseBlock() { return Branches[1]; } /// Return the list of basic blocks that this terminator can branch to. - ArrayRef successors() { return llvm::ArrayRef(Branches); } + ArrayRef successors() const { return llvm::ArrayRef(Branches); } template typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1470,7 +1466,7 @@ public: static bool classof(const SExpr *E) { return E->opcode() == COP_Return; } /// Return an empty list. - ArrayRef successors() { return {}; } + ArrayRef successors() const { return {}; } SExpr *returnValue() { return Retval; } const SExpr *returnValue() const { return Retval; } @@ -1490,7 +1486,7 @@ private: SExpr* Retval; }; -inline ArrayRef Terminator::successors() { +inline ArrayRef Terminator::successors() const { switch (opcode()) { case COP_Goto: return cast(this)->successors(); case COP_Branch: return cast(this)->successors(); diff --git a/clang/include/clang/Analysis/CallGraph.h b/clang/include/clang/Analysis/CallGraph.h index 78f8d115550178e44e3e9fe84f34e0d2cbe55c4a..c11d163f8fe20dc1a18db5291b3eb8e1eff5ee40 100644 --- a/clang/include/clang/Analysis/CallGraph.h +++ b/clang/include/clang/Analysis/CallGraph.h @@ -18,7 +18,8 @@ #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H #include "clang/AST/Decl.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" @@ -39,7 +40,7 @@ class Stmt; /// The call graph extends itself with the given declarations by implementing /// the recursive AST visitor, which constructs the graph by visiting the given /// declarations. -class CallGraph : public RecursiveASTVisitor { +class CallGraph : public DynamicRecursiveASTVisitor { friend class CallGraphNode; using FunctionMapTy = @@ -109,7 +110,7 @@ public: /// Part of recursive declaration visitation. We recursively visit all the /// declarations to collect the root functions. - bool VisitFunctionDecl(FunctionDecl *FD) { + bool VisitFunctionDecl(FunctionDecl *FD) override { // We skip function template definitions, as their semantics is // only determined when they are instantiated. if (includeInGraph(FD) && FD->isThisDeclarationADefinition()) { @@ -124,7 +125,7 @@ public: } /// Part of recursive declaration visitation. - bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { + bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override { if (includeInGraph(MD)) { addNodesForBlocks(MD); addNodeForDecl(MD, true); @@ -133,11 +134,7 @@ public: } // We are only collecting the declarations, so do not step into the bodies. - bool TraverseStmt(Stmt *S) { return true; } - - bool shouldWalkTypesOfTypeLocs() const { return false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } + bool TraverseStmt(Stmt *S) override { return true; } private: /// Add the given declaration to the call graph. diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index ec4d041254877fdc4230adf1645bea6a3be12733..6294c810626a701af8f91a68e424bb3bea09c4a6 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -14,8 +14,9 @@ #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ASTOPS_H #include "clang/AST/Decl.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "llvm/ADT/DenseSet.h" @@ -88,14 +89,14 @@ private: /// the function to analyze. Don't call `TraverseDecl()` on the function itself; /// this won't work as `TraverseDecl()` contains code to avoid traversing nested /// functions. -template -class AnalysisASTVisitor : public RecursiveASTVisitor { +class AnalysisASTVisitor : public DynamicRecursiveASTVisitor { public: - bool shouldVisitImplicitCode() { return true; } - - bool shouldVisitLambdaBody() const { return false; } + AnalysisASTVisitor() { + ShouldVisitImplicitCode = true; + ShouldVisitLambdaBody = false; + } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { // Don't traverse nested record or function declarations. // - We won't be analyzing code contained in these anyway // - We don't model fields that are used only in these nested declaration, @@ -104,30 +105,30 @@ public: if (isa_and_nonnull(D) || isa_and_nonnull(D)) return true; - return RecursiveASTVisitor::TraverseDecl(D); + return DynamicRecursiveASTVisitor::TraverseDecl(D); } // Don't traverse expressions in unevaluated contexts, as we don't model // fields that are only used in these. // Note: The operand of the `noexcept` operator is an unevaluated operand, but // nevertheless it appears in the Clang CFG, so we don't exclude it here. - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) { return true; } - bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) { + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; } + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; } + bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override { if (TIE->isPotentiallyEvaluated()) - return RecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); + return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); return true; } - bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) { + bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) override { return true; } - bool TraverseBindingDecl(BindingDecl *BD) { + bool TraverseBindingDecl(BindingDecl *BD) override { // `RecursiveASTVisitor` doesn't traverse holding variables for // `BindingDecl`s by itself, so we need to tell it to. if (VarDecl *HoldingVar = BD->getHoldingVar()) TraverseDecl(HoldingVar); - return RecursiveASTVisitor::TraverseBindingDecl(BD); + return DynamicRecursiveASTVisitor::TraverseBindingDecl(BD); } }; diff --git a/clang/include/clang/Basic/AArch64SVEACLETypes.def b/clang/include/clang/Basic/AArch64SVEACLETypes.def index 62f6087e96246626b468468e79322c91557ceca2..063cac1f4a58ee71bbbd511d32ef6729e24be59b 100644 --- a/clang/include/clang/Basic/AArch64SVEACLETypes.def +++ b/clang/include/clang/Basic/AArch64SVEACLETypes.def @@ -200,7 +200,7 @@ SVE_PREDICATE_TYPE_ALL("__clang_svboolx4_t", "svboolx4_t", SveBoolx4, SveBoolx4T SVE_OPAQUE_TYPE("__SVCount_t", "__SVCount_t", SveCount, SveCountTy) -AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8_t", "__MFloat8_t", MFloat8, MFloat8Ty, 1, 8, 1) +AARCH64_VECTOR_TYPE_MFLOAT("__mfp8", "__mfp8", MFloat8, MFloat8Ty, 1, 8, 1) AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x8_t", "__MFloat8x8_t", MFloat8x8, MFloat8x8Ty, 8, 8, 1) AARCH64_VECTOR_TYPE_MFLOAT("__MFloat8x16_t", "__MFloat8x16_t", MFloat8x16, MFloat8x16Ty, 16, 8, 1) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 38022ff9843da10227bdbb2fa03917480ac87083..2e8b0ac27af46ce5d681f7fe875f6d39321c5079 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -477,6 +477,9 @@ def TargetELF : TargetSpec { def TargetELFOrMachO : TargetSpec { let ObjectFormats = ["ELF", "MachO"]; } +def TargetIFuncSupport : TargetSpec { + let CustomCode = [{ Target.supportsIFunc() }]; +} def TargetWindowsArm64EC : TargetSpec { let CustomCode = [{ Target.getTriple().isWindowsArm64EC() }]; } @@ -1855,7 +1858,7 @@ def IBOutletCollection : InheritableAttr { let Documentation = [Undocumented]; } -def IFunc : Attr, TargetSpecificAttr { +def IFunc : Attr, TargetSpecificAttr { let Spellings = [GCC<"ifunc">]; let Args = [StringArgument<"Resolver">]; let Subjects = SubjectList<[Function]>; @@ -1889,6 +1892,37 @@ def LifetimeBound : DeclOrTypeAttr { let SimpleHandler = 1; } +def LifetimeCaptureBy : DeclOrTypeAttr { + let Spellings = [Clang<"lifetime_capture_by", 0>]; + let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>; + let Args = [VariadicParamOrParamIdxArgument<"Params">]; + let Documentation = [LifetimeCaptureByDocs]; + let AdditionalMembers = [{ +private: + ArrayRef ArgIdents; + ArrayRef ArgLocs; + +public: + static constexpr int THIS = 0; + static constexpr int INVALID = -1; + static constexpr int UNKNOWN = -2; + static constexpr int GLOBAL = -3; + + void setArgs(ArrayRef Idents, ArrayRef Locs) { + assert(Idents.size() == params_Size); + assert(Locs.size() == params_Size); + ArgIdents = Idents; + ArgLocs = Locs; + } + auto getArgIdents() const { return ArgIdents; } + auto getArgLocs() const { return ArgLocs; } + void setParamIdx(size_t Idx, int Val) { + assert(Idx < params_Size); + params_[Idx] = Val; + } +}]; +} + def TrivialABI : InheritableAttr { // This attribute does not have a C [[]] spelling because it requires the // CPlusPlus language option. @@ -4854,3 +4888,10 @@ def ClspvLibclcBuiltin: InheritableAttr { let Documentation = [ClspvLibclcBuiltinDoc]; let SimpleHandler = 1; } + +def NoTrivialAutoVarInit: InheritableAttr { + let Spellings = [Declspec<"no_init_all">]; + let Subjects = SubjectList<[Function, Tag]>; + let Documentation = [NoTrivialAutoVarInitDocs]; + let SimpleHandler = 1; +} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index b64dbef6332e6a8983982627841e86f5c2928f71..6fb2eb3eb3e663bebb63aa07884d410400f918e7 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3918,6 +3918,116 @@ have their lifetimes extended. }]; } +def LifetimeCaptureByDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Similar to `lifetimebound`_, the ``lifetime_capture_by(X)`` attribute on a +function parameter or implicit object parameter indicates that the capturing +entity ``X`` may refer to the object referred by that parameter. + +Below is a list of types of the parameters and what they're considered to refer to: + +- A reference param (of non-view type) is considered to refer to its referenced object. +- A pointer param (of non-view type) is considered to refer to its pointee. +- View type param (type annotated with ``[[gsl::Pointer()]]``) is considered to refer + to its pointee (gsl owner). This holds true even if the view type appears as a reference + in the parameter. For example, both ``std::string_view`` and + ``const std::string_view &`` are considered to refer to a ``std::string``. +- A ``std::initializer_list`` is considered to refer to its underlying array. +- Aggregates (arrays and simple ``struct``\s) are considered to refer to all + objects that their transitive subobjects refer to. + +Clang would diagnose when a temporary object is used as an argument to such an +annotated parameter. +In this case, the capturing entity ``X`` could capture a dangling reference to this +temporary object. + +.. code-block:: c++ + + void addToSet(std::string_view a [[clang::lifetime_capture_by(s)]], std::set& s) { + s.insert(a); + } + void use() { + std::set s; + addToSet(std::string(), s); // Warning: object whose reference is captured by 's' will be destroyed at the end of the full-expression. + // ^^^^^^^^^^^^^ + std::string local; + addToSet(local, s); // Ok. + } + +The capturing entity ``X`` can be one of the following: + +- Another (named) function parameter. + + .. code-block:: c++ + + void addToSet(std::string_view a [[clang::lifetime_capture_by(s)]], std::set& s) { + s.insert(a); + } + +- ``this`` (in case of member functions). + + .. code-block:: c++ + + class S { + void addToSet(std::string_view a [[clang::lifetime_capture_by(this)]]) { + s.insert(a); + } + std::set s; + }; + +- `global`, `unknown`. + + .. code-block:: c++ + + std::set s; + void addToSet(std::string_view a [[clang::lifetime_capture_by(global)]]) { + s.insert(a); + } + void addSomewhere(std::string_view a [[clang::lifetime_capture_by(unknown)]]); + +The attribute can be applied to the implicit ``this`` parameter of a member +function by writing the attribute after the function type: + +.. code-block:: c++ + + struct S { + const char *data(std::set& s) [[clang::lifetime_capture_by(s)]] { + s.insert(this); + } + }; + +The attribute supports specifying more than one capturing entities: + +.. code-block:: c++ + + void addToSets(std::string_view a [[clang::lifetime_capture_by(s1, s2)]], + std::set& s1, + std::set& s2) { + s1.insert(a); + s2.insert(a); + } + +Limitation: The capturing entity ``X`` is not used by the analysis and is +used for documentation purposes only. This is because the analysis is +statement-local and only detects use of a temporary as an argument to the +annotated parameter. + +.. code-block:: c++ + + void addToSet(std::string_view a [[clang::lifetime_capture_by(s)]], std::set& s); + void use() { + std::set s; + if (foo()) { + std::string str; + addToSet(str, s); // Not detected. + } + } + +.. _`lifetimebound`: https://clang.llvm.org/docs/AttributeReference.html#lifetimebound + }]; +} + def TrivialABIDocs : Documentation { let Category = DocCatDecl; let Content = [{ @@ -3948,7 +4058,8 @@ purposes of calls. For example: If a type is trivial for the purposes of calls, has a non-trivial destructor, and is passed as an argument by value, the convention is that the callee will -destroy the object before returning. +destroy the object before returning. The lifetime of the copy of the parameter +in the caller ends without a destructor call when the call begins. If a type is trivial for the purpose of calls, it is assumed to be trivially relocatable for the purpose of ``__is_trivially_relocatable``. @@ -5981,12 +6092,19 @@ declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline. -Not all targets support this attribute. ELF target support depends on both the -linker and runtime linker, and is available in at least lld 4.0 and later, -binutils 2.20.1 and later, glibc v2.11.1 and later, and FreeBSD 9.1 and later. -Mach-O targets support it, but with slightly different semantics: the resolver -is run at first call, instead of at load time by the runtime linker. Targets -other than ELF and Mach-O currently do not support this attribute. +Not all targets support this attribute: + +- ELF target support depends on both the linker and runtime linker, and is + available in at least lld 4.0 and later, binutils 2.20.1 and later, glibc + v2.11.1 and later, and FreeBSD 9.1 and later. +- Mach-O targets support it, but with slightly different semantics: the resolver + is run at first call, instead of at load time by the runtime linker. +- Windows target supports it on AArch64, but with different semantics: the + ``ifunc`` is replaced with a global function pointer, and the call is replaced + with an indirect call. The function pointer is initialized by a constructor + that calls the resolver. +- Baremetal target supports it on AVR. +- Other targets currently do not support this attribute. }]; } @@ -8642,6 +8760,18 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V compiler) to identify func }]; } +def NoTrivialAutoVarInitDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ +The ``__declspec(no_init_all)`` attribute disables the automatic initialization that the +`-ftrivial-auto-var-init`_ flag would have applied to locals in a marked function, or instances of +a marked type. Note that this attribute has no effect for locals that are automatically initialized +without the `-ftrivial-auto-var-init`_ flag. + +.. _`-ftrivial-auto-var-init`: ClangCommandLineReference.html#cmdoption-clang-ftrivial-auto-var-init +}]; +} + def DocCatNonBlockingNonAllocating : DocumentationCategory<"Performance Constraint Attributes"> { let Content = [{ The ``nonblocking``, ``blocking``, ``nonallocating`` and ``allocating`` attributes can be attached diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 4360e0bf9840f13f22e824262712aa12d17ff2bf..aa65f94e68f9c3d4ab8a139cc7e040cfa7af17a2 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -227,10 +227,10 @@ def FminimumNumF16F128 : Builtin, F16F128MathTemplate { let Prototype = "T(T, T)"; } -def Atan2F128 : Builtin { - let Spellings = ["__builtin_atan2f128"]; +def Atan2F16F128 : Builtin, F16F128MathTemplate { + let Spellings = ["__builtin_atan2"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, ConstIgnoringErrnoAndExceptions]; - let Prototype = "__float128(__float128, __float128)"; + let Prototype = "T(T, T)"; } def CopysignF16 : Builtin { @@ -1498,19 +1498,19 @@ def ReduceOr : Builtin { def ReduceAnd : Builtin { let Spellings = ["__builtin_reduce_and"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ReduceAdd : Builtin { let Spellings = ["__builtin_reduce_add"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ReduceMul : Builtin { let Spellings = ["__builtin_reduce_mul"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } @@ -1995,6 +1995,12 @@ def AtomicThreadFence : Builtin { let Prototype = "void(int)"; } +def ScopedAtomicThreadFence : Builtin { + let Spellings = ["__scoped_atomic_thread_fence"]; + let Attributes = [NoThrow]; + let Prototype = "void(int, int)"; +} + def AtomicSignalFence : Builtin { let Spellings = ["__atomic_signal_fence"]; let Attributes = [NoThrow]; @@ -4895,6 +4901,12 @@ def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLClip: LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_clip"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // Builtins for XRay. def XRayCustomEvent : Builtin { let Spellings = ["__xray_customevent"]; diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 8f44afa40593865c0399fc08925060990ece6879..7ce8f2c1669d6702dcb79e4e72a1cd773941343d 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -431,6 +431,14 @@ TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f32, "iffiIb", "nc", "fp8-conversion- TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f32, "ifiiIi", "nc", "fp8-conversion-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f32, "ifiiIi", "nc", "fp8-conversion-insts") +//===----------------------------------------------------------------------===// +// GFX950 only builtins. +//===----------------------------------------------------------------------===// +TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_f16, "V4fV8hV8hV4fIiIiIi", "nc", "gfx950-insts") +TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_f16, "V16fV8hV8hV16fIiIiIi", "nc", "gfx950-insts") + +TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_bf16, "V16fV8yV8yV16fIiIiIi", "nc", "gfx950-insts") + //===----------------------------------------------------------------------===// // GFX12+ only builtins. //===----------------------------------------------------------------------===// @@ -522,5 +530,7 @@ TARGET_BUILTIN(__builtin_amdgcn_swmmac_f32_16x16x32_fp8_bf8_w64, "V4fiV2iV4fs", TARGET_BUILTIN(__builtin_amdgcn_swmmac_f32_16x16x32_bf8_fp8_w64, "V4fiV2iV4fs", "nc", "gfx12-insts,wavefrontsize64") TARGET_BUILTIN(__builtin_amdgcn_swmmac_f32_16x16x32_bf8_bf8_w64, "V4fiV2iV4fs", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_prng_b32, "UiUi", "nc", "prng-inst") + #undef BUILTIN #undef TARGET_BUILTIN diff --git a/clang/include/clang/Basic/BuiltinsLoongArchLASX.def b/clang/include/clang/Basic/BuiltinsLoongArchLASX.def index f644b820a618988aaf63b26dec0ea320cc00d7c0..c4ea46a3bc5b51047092bc3eb9a34e08408cfb4a 100644 --- a/clang/include/clang/Basic/BuiltinsLoongArchLASX.def +++ b/clang/include/clang/Basic/BuiltinsLoongArchLASX.def @@ -371,7 +371,7 @@ TARGET_BUILTIN(__builtin_lasx_xvor_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvxor_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvnor_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvandn_v, "V32UcV32UcV32Uc", "nc", "lasx") -TARGET_BUILTIN(__builtin_lasx_xvorn_v, "V32ScV32ScV32Sc", "nc", "lasx") +TARGET_BUILTIN(__builtin_lasx_xvorn_v, "V32UcV32UcV32Uc", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvandi_b, "V32UcV32UcIUi", "nc", "lasx") TARGET_BUILTIN(__builtin_lasx_xvori_b, "V32UcV32UcIUi", "nc", "lasx") diff --git a/clang/include/clang/Basic/BuiltinsLoongArchLSX.def b/clang/include/clang/Basic/BuiltinsLoongArchLSX.def index b3056971986d199f0941cb6c01d2364078fcf912..a823783af88c4f80cc1851402285010087fc9647 100644 --- a/clang/include/clang/Basic/BuiltinsLoongArchLSX.def +++ b/clang/include/clang/Basic/BuiltinsLoongArchLSX.def @@ -355,7 +355,7 @@ TARGET_BUILTIN(__builtin_lsx_vor_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vxor_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vnor_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vandn_v, "V16UcV16UcV16Uc", "nc", "lsx") -TARGET_BUILTIN(__builtin_lsx_vorn_v, "V16ScV16ScV16Sc", "nc", "lsx") +TARGET_BUILTIN(__builtin_lsx_vorn_v, "V16UcV16UcV16Uc", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vandi_b, "V16UcV16UcIUi", "nc", "lsx") TARGET_BUILTIN(__builtin_lsx_vori_b, "V16UcV16UcIUi", "nc", "lsx") diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index c93ea27f164e34d000846e8677faea0390089b57..352b3a9ec594a7461483779afcdcdcb459bdeaf0 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -660,6 +660,9 @@ TARGET_BUILTIN(__builtin_ia32_vpdpbuud256, "V8iV8iV8iV8i", "ncV:256:", "avxvnnii TARGET_BUILTIN(__builtin_ia32_vpdpbuuds128, "V4iV4iV4iV4i", "ncV:128:", "avxvnniint8|avx10.2-256") TARGET_BUILTIN(__builtin_ia32_vpdpbuuds256, "V8iV8iV8iV8i", "ncV:256:", "avxvnniint8|avx10.2-256") +// MOVRS +TARGET_BUILTIN(__builtin_ia32_prefetchrs, "vvC*", "nc", "movrs") + TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2dvC*V2OiUcIi", "nV:128:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2OiV2OivC*V2OiUcIi", "nV:128:", "avx512vl") TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4dvC*V4OiUcIi", "nV:256:", "avx512vl") diff --git a/clang/include/clang/Basic/BuiltinsX86_64.def b/clang/include/clang/Basic/BuiltinsX86_64.def index f853b4313dae072bc8d61f54bf140f8cc8275f6f..57928a14b3b399bf1c352ac23db05c095c29005f 100644 --- a/clang/include/clang/Basic/BuiltinsX86_64.def +++ b/clang/include/clang/Basic/BuiltinsX86_64.def @@ -139,6 +139,12 @@ TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1rs_internal, "vUsUsUsV256i*V256i*vC*z", TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1t1_internal, "vUsUsUsV256i*V256i*vC*z", "n", "amx-transpose") TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1rst1_internal, "vUsUsUsV256i*V256i*vC*z", "n", "amx-movrs,amx-transpose") TARGET_BUILTIN(__builtin_ia32_ttransposed_internal, "V256iUsUsV256i", "n", "amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttdpbf16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-bf16,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttdpfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp16,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttcmmimfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttcmmrlfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_tconjtcmmimfp16ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-complex,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_tconjtfp16_internal, "V256iUsUsV256i", "n", "amx-complex,amx-transpose") TARGET_BUILTIN(__builtin_ia32_tcvtrowd2ps_internal, "V16fUsUsV256iUi", "n", "amx-avx512,avx10.2-512") TARGET_BUILTIN(__builtin_ia32_tcvtrowps2pbf16h_internal, "V32yUsUsV256iUi", "n", "amx-avx512,avx10.2-512") @@ -148,6 +154,10 @@ TARGET_BUILTIN(__builtin_ia32_tcvtrowps2phl_internal, "V32xUsUsV256iUi", "n", "a TARGET_BUILTIN(__builtin_ia32_tilemovrow_internal, "V16iUsUsV256iUi", "n", "amx-avx512,avx10.2-512") TARGET_BUILTIN(__builtin_ia32_tmmultf32ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-tf32") TARGET_BUILTIN(__builtin_ia32_ttmmultf32ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-tf32,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_tdpbf8ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp8") +TARGET_BUILTIN(__builtin_ia32_tdpbhf8ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp8") +TARGET_BUILTIN(__builtin_ia32_tdphbf8ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp8") +TARGET_BUILTIN(__builtin_ia32_tdphf8ps_internal, "V256iUsUsUsV256iV256iV256i", "n", "amx-fp8") // AMX TARGET_BUILTIN(__builtin_ia32_tile_loadconfig, "vvC*", "n", "amx-tile") @@ -181,6 +191,12 @@ TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz0t1, "vIUcvC*z", "n","amx-transpose") TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1, "vIUcvC*z", "n", "amx-transpose") TARGET_BUILTIN(__builtin_ia32_t2rpntlvwz1t1, "vIUcvC*z", "n","amx-transpose") TARGET_BUILTIN(__builtin_ia32_ttransposed, "vIUcIUc", "n", "amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttdpbf16ps, "vIUcIUcIUc", "n", "amx-bf16,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttdpfp16ps, "vIUcIUcIUc", "n", "amx-fp16,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttcmmimfp16ps, "vIUcIUcIUc", "n", "amx-complex,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_ttcmmrlfp16ps, "vIUcIUcIUc", "n", "amx-complex,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_tconjtcmmimfp16ps, "vIUcIUcIUc", "n", "amx-complex,amx-transpose") +TARGET_BUILTIN(__builtin_ia32_tconjtfp16, "vIUcIUc", "n", "amx-complex,amx-transpose") TARGET_BUILTIN(__builtin_ia32_tcvtrowd2ps, "V16fIUcUi", "n", "amx-avx512,avx10.2-512") TARGET_BUILTIN(__builtin_ia32_tcvtrowps2pbf16h, "V32yIUcUi", "n", "amx-avx512,avx10.2-512") @@ -212,6 +228,12 @@ TARGET_BUILTIN(__builtin_ia32_aand64, "vv*SOi", "n", "raoint") TARGET_BUILTIN(__builtin_ia32_aor64, "vv*SOi", "n", "raoint") TARGET_BUILTIN(__builtin_ia32_axor64, "vv*SOi", "n", "raoint") +// MOVRS +TARGET_BUILTIN(__builtin_ia32_movrsqi, "ScvC*", "n", "movrs") +TARGET_BUILTIN(__builtin_ia32_movrshi, "SsvC*", "n", "movrs") +TARGET_BUILTIN(__builtin_ia32_movrssi, "SivC*", "n", "movrs") +TARGET_BUILTIN(__builtin_ia32_movrsdi, "SLLivC*", "n", "movrs") + // MOVRS and AVX10.2 TARGET_BUILTIN(__builtin_ia32_vmovrsb128, "V16cV16cC*", "nV:128:", "movrs,avx10.2-256") TARGET_BUILTIN(__builtin_ia32_vmovrsb256, "V32cV32cC*", "nV:256:", "movrs,avx10.2-256") diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 104ad81ce7d1f35a749de09ec52c73ed7bb70810..684e8947595de3f1c883e8ac6e432eabe32f3b97 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -155,6 +155,7 @@ VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0) CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and ///< generates a 'patchable-function' attribute. +CODEGENOPT(TlsGuards , 1, 1) ///< Controls emission of tls guards via -fms-tls-guards CODEGENOPT(JMCInstrument, 1, 0) ///< Set when -fjmc is enabled. CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled. diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h index 7b4f435dc39f291e450632b7d11ae4d1f2833c59..c2a4addf488df1b4b84c8b77ce0b474ac020a181 100644 --- a/clang/include/clang/Basic/Cuda.h +++ b/clang/include/clang/Basic/Cuda.h @@ -103,9 +103,11 @@ enum class OffloadArch { GFX909, GFX90a, GFX90c, + GFX9_4_GENERIC, GFX940, GFX941, GFX942, + GFX950, GFX10_1_GENERIC, GFX1010, GFX1011, diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 072392e80543741b75915b5e160dd7b04d360373..d271accca3d3b792fd465988891bdc41286b1735 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -23,7 +23,6 @@ #include "llvm/ADT/FunctionExtras.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" #include @@ -561,7 +560,7 @@ private: ArgToStringFnTy ArgToStringFn; /// Whether the diagnostic should be suppressed in FilePath. - llvm::unique_function + llvm::unique_function DiagSuppressionMapping; public: @@ -973,8 +972,7 @@ public: /// These take presumed locations into account, and can still be overriden by /// clang-diagnostics pragmas. void setDiagSuppressionMapping(llvm::MemoryBuffer &Input); - bool isSuppressedViaMapping(diag::kind DiagId, - llvm::StringRef FilePath) const; + bool isSuppressedViaMapping(diag::kind DiagId, StringRef FilePath) const; /// Issue the message to the client. /// diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 457abea0b81471cc7fcd44aba7b23932e65570c0..f4a155bb00bb377e715ebe4bf5341ac028288fc9 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -364,9 +364,9 @@ def err_target_unsupported_abi_with_fpu : Error< def err_ppc_impossible_musttail: Error< "'musttail' attribute for this call is impossible because %select{" - "long calls can not be tail called on PPC|" - "indirect calls can not be tail called on PPC|" - "external calls can not be tail called on PPC}0" + "long calls cannot be tail called on PPC|" + "indirect calls cannot be tail called on PPC|" + "external calls cannot be tail called on PPC}0" >; def err_aix_musttail_unsupported: Error< "'musttail' attribute is not supported on AIX">; @@ -389,14 +389,14 @@ def remark_sloc_usage : Remark< "source manager location address space usage:">, InGroup>, DefaultRemark, ShowInSystemHeader; def note_total_sloc_usage : Note< - "%0B (%1B) in local locations, %2B (%3B) " - "in locations loaded from AST files, for a total of %4B (%5B) " - "(%6%% of available space)">; + "%0B (%human0B) in local locations, %1B (%human1B) " + "in locations loaded from AST files, for a total of %2B (%human2B) " + "(%3%% of available space)">; def note_file_sloc_usage : Note< - "file entered %0 time%s0 using %1B (%2B) of space" - "%plural{0:|: plus %3B (%4B) for macro expansions}3">; + "file entered %0 time%s0 using %1B (%human1B) of space" + "%plural{0:|: plus %2B (%human2B) for macro expansions}2">; def note_file_misc_sloc_usage : Note< - "%0 additional files entered using a total of %1B (%2B) of space">; + "%0 additional files entered using a total of %1B (%human1B) of space">; // Modules def err_module_format_unhandled : Error< diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 6ebf00d3886fe81932dd7c0d77c5d9260075b614..95ed967ad16ad7aa18b47134b791bf326d6128b8 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -557,7 +557,7 @@ def err_test_module_file_extension_format : Error< "'blockname:major:minor:hashed:user info'">; def err_drv_module_output_with_multiple_arch : Error< - "option '-fmodule-output' can't be used with multiple arch options">; + "option '-fmodule-output' cannot be used with multiple arch options">; def warn_drv_delayed_template_parsing_after_cxx20 : Warning< "-fdelayed-template-parsing is deprecated after C++20">, diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 72eada50a56cc9efde8076d17a7ad63382a22934..df9bf94b5d0398feb9e70f394d2de46b3945ab90 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -453,6 +453,7 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingAssignment: DiagGroup<"dangling-assignment">; def DanglingAssignmentGsl : DiagGroup<"dangling-assignment-gsl">; +def DanglingCapture : DiagGroup<"dangling-capture">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; def DanglingInitializerList : DiagGroup<"dangling-initializer-list">; @@ -462,6 +463,7 @@ def ReturnStackAddress : DiagGroup<"return-stack-address">; def : DiagGroup<"return-local-addr", [ReturnStackAddress]>; def Dangling : DiagGroup<"dangling", [DanglingAssignment, DanglingAssignmentGsl, + DanglingCapture, DanglingField, DanglingInitializerList, DanglingGsl, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 1254f0247e50a6f7c67aacb26262769d910e478c..0c70dcb941e6560dd1d0a28e975d6a6d1eafa134 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -976,7 +976,7 @@ def warn_cxx98_compat_defaulted_deleted_function : Warning< "%select{defaulted|deleted}0 function definitions are incompatible with C++98">, InGroup, DefaultIgnore; -def ext_delete_with_message : ExtWarn< +def ext_delete_with_message : Extension< "'= delete' with a message is a C++2c extension">, InGroup; def warn_cxx23_delete_with_message : Warning< "'= delete' with a message is incompatible with C++ standards before C++2c">, diff --git a/clang/include/clang/Basic/DiagnosticRefactoringKinds.td b/clang/include/clang/Basic/DiagnosticRefactoringKinds.td index 5446b32efbdd47e4ad6ee81779bafd1d18a70519..e060fffc7280a79278d7c54eb00b1de55dbce3c7 100644 --- a/clang/include/clang/Basic/DiagnosticRefactoringKinds.td +++ b/clang/include/clang/Basic/DiagnosticRefactoringKinds.td @@ -14,7 +14,7 @@ let Component = "Refactoring" in { let CategoryName = "Refactoring Invocation Issue" in { -def err_refactor_no_selection : Error<"refactoring action can't be initiated " +def err_refactor_no_selection : Error<"refactoring action cannot be initiated " "without a selection">; def err_refactor_selection_no_symbol : Error<"there is no symbol at the given " "location">; @@ -26,7 +26,7 @@ def err_refactor_code_outside_of_function : Error<"the selected code is not a " def err_refactor_extract_simple_expression : Error<"the selected expression " "is too simple to extract">; def err_refactor_extract_prohibited_expression : Error<"the selected " - "expression can't be extracted">; + "expression cannot be extracted">; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index cdc9ad9f806e1cfbe9f645d823462fa32a83c8f4..5ff489fa93b4bf770906a318e8e53e445964a45d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1151,7 +1151,7 @@ def err_pragma_attribute_matcher_subrule_contradicts_rule : Error< def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error< "negated attribute subject matcher sub-rule '%0' contradicts sub-rule '%1'">; def err_pragma_attribute_invalid_matchers : Error< - "attribute %0 can't be applied to %1">; + "attribute %0 cannot be applied to %1">; def err_pragma_attribute_stack_mismatch : Error< "'#pragma clang attribute %select{%1.|}0pop' with no matching" " '#pragma clang attribute %select{%1.|}0push'">; @@ -3383,6 +3383,20 @@ def err_callback_callee_is_variadic : Error< "'callback' attribute callee may not be variadic">; def err_callback_implicit_this_not_available : Error< "'callback' argument at position %0 references unavailable implicit 'this'">; + +def err_capture_by_attribute_multiple : Error< + "multiple 'lifetime_capture' attributes specified">; +def err_capture_by_attribute_no_entity : Error< + "'lifetime_capture_by' attribute specifies no capturing entity">; +def err_capture_by_implicit_this_not_available : Error< + "'lifetime_capture_by' argument references unavailable implicit 'this'">; +def err_capture_by_attribute_argument_unknown : Error< + "'lifetime_capture_by' attribute argument %0 is not a known function parameter" + "; must be a function parameter, 'this', 'global' or 'unknown'">; +def err_capture_by_references_itself : Error<"'lifetime_capture_by' argument references itself">; +def err_capture_by_param_uses_reserved_name : Error< + "parameter cannot be named '%select{global|unknown}0' while using 'lifetime_capture_by(%select{global|unknown}0)'">; + def err_init_method_bad_return_type : Error< "init methods must return an object pointer type, not %0">; def err_attribute_invalid_size : Error< @@ -6136,7 +6150,7 @@ def err_mismatched_owning_module : Error< "declaration of %0 in %select{the global module|module %2}1 follows " "declaration in %select{the global module|module %4}3">; def err_multiple_decl_in_different_modules : Error< - "declaration %0 attached to named module '%1' can't be attached to " + "declaration %0 attached to named module '%1' cannot be attached to " "other modules">; def err_redefinition_different_type : Error< "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; @@ -8546,7 +8560,7 @@ def err_typecheck_missing_return_type_incompatible : Error< "literal|lambda expression}2 has unspecified explicit return type">; def note_incomplete_class_and_qualified_id : Note< - "conformance of forward class %0 to protocol %1 can not be confirmed">; + "conformance of forward class %0 to protocol %1 cannot be confirmed">; def warn_incompatible_qualified_id : Warning< "%select{%diff{assigning to $ from incompatible type $|" "assigning to type from incompatible type}0,1" @@ -9286,11 +9300,11 @@ def warn_unused_container_subscript_expr : Warning< def warn_unused_call : Warning< "ignoring return value of function declared with %0 attribute">, InGroup; -def warn_unused_constructor : Warning< - "ignoring temporary created by a constructor declared with %0 attribute">, +def warn_unused_return_type : Warning< + "ignoring %select{return value|temporary}0 of type %2 declared with %1 attribute%select{|: %4}3">, InGroup; -def warn_unused_constructor_msg : Warning< - "ignoring temporary created by a constructor declared with %0 attribute: %1">, +def warn_unused_constructor : Warning< + "ignoring temporary created by a constructor declared with %0 attribute%select{|: %2}1">, InGroup; def warn_side_effects_unevaluated_context : Warning< "expression with side effects has no effect in an unevaluated context">, @@ -9299,10 +9313,7 @@ def warn_side_effects_typeid : Warning< "expression with side effects will be evaluated despite being used as an " "operand to 'typeid'">, InGroup; def warn_unused_result : Warning< - "ignoring return value of function declared with %0 attribute">, - InGroup; -def warn_unused_result_msg : Warning< - "ignoring return value of function declared with %0 attribute: %1">, + "ignoring return value of function declared with %0 attribute%select{|: %2}1">, InGroup; def warn_unused_result_typedef_unsupported_spelling : Warning< "'[[%select{nodiscard|gnu::warn_unused_result}0]]' attribute ignored when " @@ -9400,7 +9411,7 @@ let CategoryName = "Inline Assembly Issue" in { "asm constraint has an unexpected number of alternatives: %0 vs %1">; def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; - def err_asm_unwind_and_goto : Error<"unwind clobber can't be used with asm goto">; + def err_asm_unwind_and_goto : Error<"unwind clobber cannot be used with asm goto">; def err_asm_invalid_global_var_reg : Error<"register '%0' unsuitable for " "global register variables on this target">; def err_asm_register_size_mismatch : Error<"size of register '%0' does not " @@ -9419,7 +9430,7 @@ let CategoryName = "Inline Assembly Issue" in { def err_asm_input_duplicate_match : Error< "more than one input constraint matches the same output '%0'">; def err_store_value_to_reg : Error< - "impossible constraint in asm: can't store value into a register">; + "impossible constraint in asm: cannot store value into a register">; def warn_asm_label_on_auto_decl : Warning< "ignored asm label '%0' on automatic variable">; @@ -10118,10 +10129,11 @@ def err_lifetimebound_ctor_dtor : Error< "%select{constructor|destructor}0">; def err_lifetimebound_parameter_void_return_type : Error< "'lifetimebound' attribute cannot be applied to a parameter of a function " - "that returns void">; + "that returns void; did you mean 'lifetime_capture_by(X)'">; def err_lifetimebound_implicit_object_parameter_void_return_type : Error< "'lifetimebound' attribute cannot be applied to an implicit object " - "parameter of a function that returns void">; + "parameter of a function that returns void; " + "did you mean 'lifetime_capture_by(X)'">; // CHECK: returning address/reference of stack memory def warn_ret_stack_addr_ref : Warning< @@ -10216,6 +10228,12 @@ def warn_dangling_pointer_assignment : Warning< "object backing %select{|the pointer }0%1 " "will be destroyed at the end of the full-expression">, InGroup; +def warn_dangling_reference_captured : Warning< + "object whose reference is captured by '%0' will be destroyed at the end of " + "the full-expression">, InGroup, DefaultIgnore; +def warn_dangling_reference_captured_by_unknown : Warning< + "object whose reference is captured will be destroyed at the end of " + "the full-expression">, InGroup, DefaultIgnore; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. @@ -10946,7 +10964,7 @@ def err_opencl_builtin_pipe_invalid_access_modifier : Error< def err_opencl_invalid_access_qualifier : Error< "access qualifier can only be used for pipe and image type">; def err_opencl_invalid_read_write : Error< - "access qualifier %0 can not be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 " + "access qualifier %0 cannot be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 " "and without __opencl_c_read_write_images feature}2">; def err_opencl_multiple_access_qualifiers : Error< "multiple access qualifiers">; @@ -11446,7 +11464,7 @@ def err_omp_wrong_linear_modifier : Error< def err_omp_wrong_linear_modifier_non_reference : Error< "variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">; def err_omp_step_simple_modifier_exclusive : Error< - "step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier">; + "step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier">; def err_omp_wrong_simdlen_safelen_values : Error< "the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">; def err_omp_wrong_if_directive_name_modifier : Error< @@ -11520,7 +11538,7 @@ def err_omp_schedule_nonmonotonic_static : Error< def err_omp_simple_clause_incompatible_with_ordered : Error< "'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">; def err_omp_ordered_simd : Error< - "'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">; + "'ordered' clause with a parameter cannot be specified in '#pragma omp %0' directive">; def err_omp_variable_in_given_clause_and_dsa : Error< "%0 variable cannot be in a %1 clause in '#pragma omp %2' directive">; def err_omp_param_or_this_in_clause : Error< @@ -12352,9 +12370,9 @@ def err_preserve_enum_value_not_const: Error< "__builtin_preserve_enum_value argument %0 not a constant">; def err_bit_cast_non_trivially_copyable : Error< - "__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">; + "'__builtin_bit_cast' %select{source|destination}0 type must be trivially copyable">; def err_bit_cast_type_size_mismatch : Error< - "__builtin_bit_cast source size does not equal destination size (%0 vs %1)">; + "size of '__builtin_bit_cast' source type %0 does not match destination type %1 (%2 vs %3 bytes)">; // SYCL-specific diagnostics def warn_sycl_kernel_num_of_template_params : Warning< @@ -12639,11 +12657,11 @@ def note_acc_previous_clause_here : Note<"previous clause is here">; def note_acc_previous_expr_here : Note<"previous expression is here">; def err_acc_branch_in_out_compute_construct : Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 " - "OpenACC Compute Construct">; + "OpenACC Compute/Combined Construct">; def note_acc_branch_into_compute_construct - : Note<"invalid branch into OpenACC Compute Construct">; + : Note<"invalid branch into OpenACC Compute/Combined Construct">; def note_acc_branch_out_of_compute_construct - : Note<"invalid branch out of OpenACC Compute Construct">; + : Note<"invalid branch out of OpenACC Compute/Combined Construct">; def warn_acc_if_self_conflict : Warning<"OpenACC construct 'self' has no effect when an 'if' clause " "evaluates to true">, @@ -12698,10 +12716,10 @@ def err_acc_var_not_pointer_type def note_acc_expected_pointer_var : Note<"expected variable of pointer type">; def err_acc_clause_after_device_type : Error<"OpenACC clause '%0' may not follow a '%1' clause in a " - "%select{'%3'|compute}2 construct">; + "'%2' construct">; def err_acc_clause_cannot_combine : Error<"OpenACC clause '%0' may not appear on the same construct as a " - "'%1' clause on a 'loop' construct">; + "'%1' clause on a '%2' construct">; def err_acc_reduction_num_gangs_conflict : Error< "OpenACC 'reduction' clause may not appear on a 'parallel' construct " @@ -12717,7 +12735,7 @@ def err_acc_reduction_composite_member_type :Error< "OpenACC 'reduction' composite variable must not have non-scalar field">; def note_acc_reduction_composite_member_loc : Note<"invalid field is here">; def err_acc_loop_not_for_loop - : Error<"OpenACC 'loop' construct can only be applied to a 'for' loop">; + : Error<"OpenACC '%0' construct can only be applied to a 'for' loop">; def note_acc_construct_here : Note<"'%0' construct is here">; def err_acc_loop_spec_conflict : Error<"OpenACC clause '%0' on '%1' construct conflicts with previous " @@ -12775,16 +12793,16 @@ def err_reduction_op_mismatch : Error<"OpenACC 'reduction' variable must have the same operator in all " "nested constructs (%0 vs %1)">; def err_acc_loop_variable_type - : Error<"loop variable of loop associated with an OpenACC 'loop' construct " + : Error<"loop variable of loop associated with an OpenACC '%0' construct " "must be of integer, pointer, or random-access-iterator type (is " - "%0)">; + "%1)">; def err_acc_loop_variable - : Error<"OpenACC 'loop' construct must have initialization clause in " + : Error<"OpenACC '%0' construct must have initialization clause in " "canonical form ('var = init' or 'T var = init')">; def err_acc_loop_terminating_condition - : Error<"OpenACC 'loop' construct must have a terminating condition">; + : Error<"OpenACC '%0' construct must have a terminating condition">; def err_acc_loop_not_monotonic - : Error<"OpenACC 'loop' variable must monotonically increase or decrease " + : Error<"OpenACC '%0' variable must monotonically increase or decrease " "('++', '--', or compound assignment)">; // AMDGCN builtins diagnostics diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 7f5d26118bdc714cee305464a9359aeda303a5ab..9088c867d53ce4fc2a510ef3709588877e3b948c 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -116,6 +116,7 @@ FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFuncti FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos) FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) FEATURE(ptrauth_init_fini_address_discrimination, LangOpts.PointerAuthInitFiniAddressDiscrimination) +FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT) EXTENSION(swiftcc, PP.getTargetInfo().checkCallingConvention(CC_Swift) == clang::TargetInfo::CCCR_OK) diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h index 4310c28bc935e8719a8a73e7a76cb3b5a91da34a..ea0bf23468cb8b47f831b58cf949621d812017d2 100644 --- a/clang/include/clang/Basic/OpenACCKinds.h +++ b/clang/include/clang/Basic/OpenACCKinds.h @@ -152,6 +152,12 @@ inline bool isOpenACCComputeDirectiveKind(OpenACCDirectiveKind K) { K == OpenACCDirectiveKind::Kernels; } +inline bool isOpenACCCombinedDirectiveKind(OpenACCDirectiveKind K) { + return K == OpenACCDirectiveKind::ParallelLoop || + K == OpenACCDirectiveKind::SerialLoop || + K == OpenACCDirectiveKind::KernelsLoop; +} + enum class OpenACCAtomicKind : uint8_t { Read, Write, diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 6046b5409bd1b0bc4081f9608791a63ee90690ae..a11bc317c9c91c4ec01e24c0f40511b1f00a913a 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -315,6 +315,7 @@ def OpenACCAssociatedStmtConstruct : StmtNode; def OpenACCComputeConstruct : StmtNode; def OpenACCLoopConstruct : StmtNode; +def OpenACCCombinedConstruct : StmtNode; // OpenACC Additional Expressions. def OpenACCAsteriskSizeExpr : StmtNode; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 25eda907d20a7bf30d0ef036d5f6776c00631cf8..9cd23d123f2bac89dc90434e7442e4bf8c32aba9 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -486,6 +486,13 @@ public: /// \param AddrSpace address space of pointee in source language. virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; } + /// Returns true if an address space can be safely converted to another. + /// \param A address space of target in source language. + /// \param B address space of source in source language. + virtual bool isAddressSpaceSupersetOf(LangAS A, LangAS B) const { + return A == B; + } + /// Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } @@ -1497,6 +1504,10 @@ public: bool supportsIFunc() const { if (getTriple().isOSBinFormatMachO()) return true; + if (getTriple().isOSWindows() && getTriple().isAArch64()) + return true; + if (getTriple().getArch() == llvm::Triple::ArchType::avr) + return true; return getTriple().isOSBinFormatELF() && ((getTriple().isOSLinux() && !getTriple().isMusl()) || getTriple().isOSFreeBSD()); @@ -1860,6 +1871,11 @@ private: void CheckFixedPointBits() const; }; +namespace targets { +std::unique_ptr +AllocateTarget(const llvm::Triple &Triple, const clang::TargetOptions &Opts); +} // namespace targets + } // end namespace clang #endif diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td index 52185ca07da41ff15c43b608b2b1c60ef5da5ae0..93abbc47c54dd5c6a61d9366104291c2569ea50b 100644 --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -193,7 +193,7 @@ multiclass FMA { def sq_m_n: Intrinsic:$addend_s, Predicate:$pred), - (seq (splat $addend_s):$addend, pred_cg)>; + (select $pred, (seq (splat $addend_s):$addend, unpred_cg), $m1)>; } } @@ -753,8 +753,8 @@ let params = T.Float in { defm: compare<"ne", fcmp_ne>; defm: compare<"gt", fcmp_gt>; defm: compare<"ge", fcmp_ge>; - defm: compare<"lt", fcmp_lt>; - defm: compare<"le", fcmp_le>; + defm: compare<"lt", fcmp_ult>; + defm: compare<"le", fcmp_ule>; } let params = T.Signed in { diff --git a/clang/include/clang/Basic/arm_mve_defs.td b/clang/include/clang/Basic/arm_mve_defs.td index 1a090c08cc8531de8a4f1d0f0e4fd22669f4b48c..634b4e9c2c9c8a251abfc4133efb058b6562ebd8 100644 --- a/clang/include/clang/Basic/arm_mve_defs.td +++ b/clang/include/clang/Basic/arm_mve_defs.td @@ -116,8 +116,8 @@ def fcmp_eq: IRBuilder<"CreateFCmpOEQ">; def fcmp_ne: IRBuilder<"CreateFCmpUNE">; // not O: it must return true on NaNs def fcmp_gt: IRBuilder<"CreateFCmpOGT">; def fcmp_ge: IRBuilder<"CreateFCmpOGE">; -def fcmp_lt: IRBuilder<"CreateFCmpOLT">; -def fcmp_le: IRBuilder<"CreateFCmpOLE">; +def fcmp_ult: IRBuilder<"CreateFCmpULT">; +def fcmp_ule: IRBuilder<"CreateFCmpULE">; def splat: CGHelperFn<"ARMMVEVectorSplat">; def select: IRBuilder<"CreateSelect">; def fneg: IRBuilder<"CreateFNeg">; diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td index ec829f566ef5fc84384c26271b35fec3b78e6743..ef89fa4358dfeb050a1336fbe2b85ba08fa43eaa 100644 --- a/clang/include/clang/Basic/arm_neon.td +++ b/clang/include/clang/Basic/arm_neon.td @@ -252,7 +252,7 @@ def OP_BFMLALT_LN def OP_VCVT_F32_BF16 : Op<(bitcast "R", - (call "vshll_n", (bitcast "int16x4_t", $p0), + (call "vshll_n", (bitcast "uint16x4_t", $p0), (literal "int32_t", "16")))>; def OP_VCVT_F32_BF16_LO : Op<(call "vcvt_f32_bf16", (call "vget_low", $p0))>; @@ -275,8 +275,8 @@ def OP_VCVT_BF16_F32_HI_A32 (call "vget_low", $p0))>; def OP_CVT_F32_BF16 - : Op<(bitcast "R", (op "<<", (cast "int32_t", (bitcast "int16_t", $p0)), - (literal "int32_t", "16")))>; + : Op<(bitcast "R", (op "<<", (cast "uint32_t", (bitcast "uint16_t", $p0)), + (literal "uint32_t", "16")))>; //===----------------------------------------------------------------------===// // Auxiliary Instructions diff --git a/clang/include/clang/Basic/arm_neon_incl.td b/clang/include/clang/Basic/arm_neon_incl.td index b088e0794cdea3e2586d750ffcd2ae23dd53540f..fd800e5a6278e4afda888df0c1859c62a424d0e7 100644 --- a/clang/include/clang/Basic/arm_neon_incl.td +++ b/clang/include/clang/Basic/arm_neon_incl.td @@ -218,6 +218,7 @@ def OP_UNAVAILABLE : Operation { // h: half-float // d: double // b: bfloat16 +// m: mfloat8 // // Typespec modifiers // ------------------ diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index 1f74e11ab06231549abb7b37044fceabed471afd..d492fae4145b921b84a60b60988f1e6b4144b8e7 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -1964,7 +1964,7 @@ let SVETargetGuard = "sve2,lut,bf16", SMETargetGuard = "sme2,lut,bf16" in { //////////////////////////////////////////////////////////////////////////////// // SVE2 - Optional -let SVETargetGuard = "sve2-aes", SMETargetGuard = InvalidMode in { +let SVETargetGuard = "sve2,sve-aes", SMETargetGuard = InvalidMode in { def SVAESD : SInst<"svaesd[_{d}]", "ddd", "Uc", MergeNone, "aarch64_sve_aesd", [IsOverloadNone]>; def SVAESIMC : SInst<"svaesimc[_{d}]", "dd", "Uc", MergeNone, "aarch64_sve_aesimc", [IsOverloadNone]>; def SVAESE : SInst<"svaese[_{d}]", "ddd", "Uc", MergeNone, "aarch64_sve_aese", [IsOverloadNone]>; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 443e4e1a0f39ddc0e19366c717ed3c837a2ea556..facf2a3263044100953821504fd4c63049f614ef 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -965,6 +965,10 @@ def V : JoinedOrSeparate<["-"], "V">, Flags<[NoXarchOption, Unsupported]>; def Wa_COMMA : CommaJoined<["-"], "Wa,">, HelpText<"Pass the comma separated arguments in to the assembler">, MetaVarName<"">; +def warning_suppression_mappings_EQ : Joined<["--"], + "warning-suppression-mappings=">, Group, + HelpText<"File containing diagnostic suppresion mappings. See user manual " + "for file format.">, Visibility<[ClangOption, CC1Option]>; def Wall : Flag<["-"], "Wall">, Group, Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option, FlangOption]>; def WCL4 : Flag<["-"], "WCL4">, Group, Flags<[HelpHidden]>, @@ -1728,8 +1732,6 @@ defm gnu_inline_asm : BoolFOption<"gnu-inline-asm", "Disable GNU style inline asm">, PosFlag>; -def fprofile_sample_use : Flag<["-"], "fprofile-sample-use">, Group, - Visibility<[ClangOption, CLOption]>; def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group, Visibility<[ClangOption, CLOption]>; def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">, @@ -1755,8 +1757,6 @@ def fsample_profile_use_profi : Flag<["-"], "fsample-profile-use-profi">, basic block counts to branch probabilites to fix them by extended and re-engineered classic MCMF (min-cost max-flow) approach.}]>; def fno_profile_sample_accurate : Flag<["-"], "fno-profile-sample-accurate">, Group; -def fauto_profile : Flag<["-"], "fauto-profile">, Group, - Alias; def fno_auto_profile : Flag<["-"], "fno-auto-profile">, Group, Alias; def fauto_profile_EQ : Joined<["-"], "fauto-profile=">, @@ -4068,6 +4068,11 @@ defm threadsafe_statics : BoolFOption<"threadsafe-statics", NegFlag, PosFlag>; +defm ms_tls_guards : BoolFOption<"ms-tls-guards", + CodeGenOpts<"TlsGuards">, DefaultTrue, + NegFlag, + PosFlag>; def ftime_report : Flag<["-"], "ftime-report">, Group, Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag>; @@ -4347,6 +4352,7 @@ defm ptrauth_indirect_gotos : OptInCC1FFlag<"ptrauth-indirect-gotos", defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">; defm ptrauth_init_fini_address_discrimination : OptInCC1FFlag<"ptrauth-init-fini-address-discrimination", "Enable address discrimination of function pointers in init/fini arrays">; +defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, @@ -8641,6 +8647,12 @@ def _SLASH_Zc_threadSafeInit : CLFlag<"Zc:threadSafeInit">, def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">, HelpText<"Disable thread-safe initialization of static variables">, Alias; +def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">, + HelpText<"Enable on-demand initialization of thread-local variables">, + Alias; +def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">, + HelpText<"Disable on-demand initialization of thread-local variables">, + Alias; def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">, HelpText<"Enable trigraphs">, Alias; def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">, @@ -9029,8 +9041,3 @@ def wasm_opt : Flag<["--"], "wasm-opt">, Group, HelpText<"Enable the wasm-opt optimizer (default)">, MarshallingInfoNegativeFlag>; - -def warning_suppression_mappings_EQ : Joined<["--"], - "warning-suppression-mappings=">, Group, - HelpText<"File containing diagnostic suppresion mappings. See user manual " - "for file format.">, Visibility<[ClangOption, CC1Option]>; diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 338eb3c6bd028d3eedb7cacf77b5ea5ecedb5d40..1220a4e29471d14890c729b788ca8ed0e7996671 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -675,13 +675,17 @@ public: /// Note that this routine also replaces the diagnostic client, /// allocating one if one is not provided. /// + /// \param VFS is used for any IO needed when creating DiagnosticsEngine. It + /// doesn't replace VFS in the CompilerInstance (if any). + /// /// \param Client If non-NULL, a diagnostic client that will be /// attached to (and, then, owned by) the DiagnosticsEngine inside this AST /// unit. /// /// \param ShouldOwnClient If Client is non-NULL, specifies whether /// the diagnostic object should take ownership of the client. - void createDiagnostics(DiagnosticConsumer *Client = nullptr, + void createDiagnostics(llvm::vfs::FileSystem &VFS, + DiagnosticConsumer *Client = nullptr, bool ShouldOwnClient = true); /// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter. @@ -702,10 +706,11 @@ public: /// used by some diagnostics printers (for logging purposes only). /// /// \return The new object on success, or null on failure. - static IntrusiveRefCntPtr createDiagnostics( - DiagnosticOptions *Opts, DiagnosticConsumer *Client = nullptr, - bool ShouldOwnClient = true, const CodeGenOptions *CodeGenOpts = nullptr, - IntrusiveRefCntPtr VFS = nullptr); + static IntrusiveRefCntPtr + createDiagnostics(llvm::vfs::FileSystem &VFS, DiagnosticOptions *Opts, + DiagnosticConsumer *Client = nullptr, + bool ShouldOwnClient = true, + const CodeGenOptions *CodeGenOpts = nullptr); /// Create the file manager and replace any existing one with it. /// diff --git a/clang/include/clang/Frontend/FrontendAction.h b/clang/include/clang/Frontend/FrontendAction.h index 039f6f247b6d8cf17fe59aee7c880d72b6ae1182..718684a67771a2232717ff09b109f03c22bf6f59 100644 --- a/clang/include/clang/Frontend/FrontendAction.h +++ b/clang/include/clang/Frontend/FrontendAction.h @@ -21,6 +21,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendOptions.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -185,7 +186,12 @@ public: virtual bool usesPreprocessorOnly() const = 0; /// For AST-based actions, the kind of translation unit we're handling. - virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; } + virtual TranslationUnitKind getTranslationUnitKind() { + // The ASTContext, if exists, knows the exact TUKind of the frondend. + if (Instance && Instance->hasASTContext()) + return Instance->getASTContext().TUKind; + return TU_Complete; + } /// Does this action support use with PCH? virtual bool hasPCHSupport() const { return true; } diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 1230a3a7016fae863fcf19544a91cf9fa959e8d3..b1b63aedf86aba2c8f3d824197b304129a97f937 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -177,7 +177,8 @@ private: CodeGenerator *getCodeGen() const; std::unique_ptr GenModule(); - PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU); + PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU, + std::unique_ptr M = {}); // A cache for the compiled destructors used to for de-allocation of managed // clang::Values. diff --git a/clang/include/clang/Interpreter/PartialTranslationUnit.h b/clang/include/clang/Interpreter/PartialTranslationUnit.h index bf91d559452b8a2469a67d84e0598728cf445cb7..c878e139fe70d011e814a1bd20f72de006f88bf3 100644 --- a/clang/include/clang/Interpreter/PartialTranslationUnit.h +++ b/clang/include/clang/Interpreter/PartialTranslationUnit.h @@ -31,6 +31,9 @@ struct PartialTranslationUnit { /// The llvm IR produced for the input. std::unique_ptr TheModule; + bool operator==(const PartialTranslationUnit &other) { + return other.TUPart == TUPart && other.TheModule == TheModule; + } }; } // namespace clang diff --git a/clang/include/clang/Parse/ParseDiagnostic.h b/clang/include/clang/Parse/ParseDiagnostic.h deleted file mode 100644 index f174464b78419c08adba59a845f729a677ec6093..0000000000000000000000000000000000000000 --- a/clang/include/clang/Parse/ParseDiagnostic.h +++ /dev/null @@ -1,14 +0,0 @@ -//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H -#define LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H - -#include "clang/Basic/DiagnosticParse.h" - -#endif diff --git a/clang/include/clang/Parse/RAIIObjectsForParser.h b/clang/include/clang/Parse/RAIIObjectsForParser.h index f4fa518ef27d01558802f0d4a6eb072f1712a230..480efccb19cf7f32cd75bfddcc9c8961862cbbd7 100644 --- a/clang/include/clang/Parse/RAIIObjectsForParser.h +++ b/clang/include/clang/Parse/RAIIObjectsForParser.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H #define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H -#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Parse/Parser.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/ParsedTemplate.h" diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index 084db7303421917d09d30325cda9c4936562883a..ad12a3d73413bd491581b0f18db1c515130b58a3 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -154,7 +154,8 @@ public: /// depth of recursion. LambdaScope = 0x8000000, /// This is the scope of an OpenACC Compute Construct, which restricts - /// jumping into/out of it. + /// jumping into/out of it. We also use this to represent 'combined' + /// constructs, since they have the same behavior. OpenACCComputeConstructScope = 0x10000000, /// This is a scope of type alias declaration. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fad446a05e782f9c78bd18a0eb1ea548c510f1b0..6ea6c67447b6f0d12d0b2f4ee4893ef7f0dd17fe 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1760,6 +1760,14 @@ public: /// Add [[gsl::Pointer]] attributes for std:: types. void inferGslPointerAttribute(TypedefNameDecl *TD); + LifetimeCaptureByAttr *ParseLifetimeCaptureByAttr(const ParsedAttr &AL, + StringRef ParamName); + // Processes the argument 'X' in [[clang::lifetime_capture_by(X)]]. Since 'X' + // can be the name of a function parameter, we need to parse the function + // declaration and rest of the parameters before processesing 'X'. Therefore + // do this lazily instead of processing while parsing the annotation itself. + void LazyProcessLifetimeCaptureByParams(FunctionDecl *FD); + /// Add _Nullable attributes for std:: types. void inferNullableClassAttribute(CXXRecordDecl *CRD); @@ -2315,6 +2323,9 @@ public: bool BuiltinVectorMath(CallExpr *TheCall, QualType &Res, bool FPOnly = false); bool BuiltinVectorToScalarMath(CallExpr *TheCall); + void checkLifetimeCaptureBy(FunctionDecl *FDecl, bool IsMemberFunction, + const Expr *ThisArg, ArrayRef Args); + /// Handles the checks for format strings, non-POD arguments to vararg /// functions, NULL arguments passed to non-NULL parameters, diagnose_if /// attributes and AArch64 SME attributes. diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 1c6ac4b0b51f404c383fccf6c9e43ad342d4cbcf..e8f022362ea168ade23f4f14e17f51453c28f569 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -170,10 +170,14 @@ public: /// 'worker' clauses. SourceLocation LoopVectorClauseLoc; /// If there is a current 'active' loop construct that does NOT have a 'seq' - /// clause on it, this has that source location. This permits us to implement - /// the 'loop' restrictions on the loop variable. This can be extended via - /// 'collapse', so we need to keep this around for a while. - SourceLocation LoopWithoutSeqLoc; + /// clause on it, this has that source location and loop Directive 'kind'. + /// This permits us to implement the 'loop' restrictions on the loop variable. + /// This can be extended via 'collapse', so we need to keep this around for a + /// while. + struct LoopWithoutSeqCheckingInfo { + OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; + SourceLocation Loc; + } LoopWithoutSeqInfo; // Redeclaration of the version in OpenACCClause.h. using DeviceTypeArgument = std::pair; @@ -762,7 +766,7 @@ public: SourceLocation OldLoopGangClauseOnKernelLoc; SourceLocation OldLoopWorkerClauseLoc; SourceLocation OldLoopVectorClauseLoc; - SourceLocation OldLoopWithoutSeqLoc; + LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo; llvm::SmallVector ActiveReductionClauses; LoopInConstructRAII LoopRAII; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index cddc4f824e3e3c534de02c0c5bc671cd4f51d178..c1eefa61357a71cdee807a74763ba5cd6c0deb52 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -44,7 +44,7 @@ namespace serialization { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. -const unsigned VERSION_MAJOR = 33; +const unsigned VERSION_MAJOR = 34; /// AST file minor version number supported by this version of /// Clang. @@ -350,9 +350,8 @@ enum ControlRecordTypes { /// and information about the compiler used to build this AST file. METADATA = 1, - /// Record code for the list of other AST files imported by - /// this AST file. - IMPORTS, + /// Record code for another AST file imported by this AST file. + IMPORT, /// Record code for the original file that was used to /// generate the AST file, including both its file ID and its @@ -2013,6 +2012,7 @@ enum StmtCode { // OpenACC Constructs/Exprs STMT_OPENACC_COMPUTE_CONSTRUCT, STMT_OPENACC_LOOP_CONSTRUCT, + STMT_OPENACC_COMBINED_CONSTRUCT, EXPR_OPENACC_ASTERISK_SIZE, // HLSL Constructs diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 9c274adc59a207330a3cbbd2c11606c43c569939..f739fe688c110dc9f22d606dbfbaf4612168ab9b 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -2389,11 +2389,8 @@ public: // Read a string static std::string ReadString(const RecordDataImpl &Record, unsigned &Idx); - - // Skip a string - static void SkipString(const RecordData &Record, unsigned &Idx) { - Idx += Record[Idx] + 1; - } + static StringRef ReadStringBlob(const RecordDataImpl &Record, unsigned &Idx, + StringRef &Blob); // Read a path std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx); @@ -2401,11 +2398,8 @@ public: // Read a path std::string ReadPath(StringRef BaseDirectory, const RecordData &Record, unsigned &Idx); - - // Skip a path - static void SkipPath(const RecordData &Record, unsigned &Idx) { - SkipString(Record, Idx); - } + std::string ReadPathBlob(StringRef BaseDirectory, const RecordData &Record, + unsigned &Idx, StringRef &Blob); /// Read a version tuple. static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 161b2ef7c86a4926ac7f74cfb79f947b9966c262..e418fdea44a0a9c429afb5f7a64f6407ef0c573e 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -769,6 +769,8 @@ public: /// Add a string to the given record. void AddString(StringRef Str, RecordDataImpl &Record); + void AddStringBlob(StringRef Str, RecordDataImpl &Record, + SmallVectorImpl &Blob); /// Convert a path from this build process into one that is appropriate /// for emission in the module file. @@ -776,6 +778,8 @@ public: /// Add a path to the given record. void AddPath(StringRef Path, RecordDataImpl &Record); + void AddPathBlob(StringRef Str, RecordDataImpl &Record, + SmallVectorImpl &Blob); /// Emit the current record with the given path as a blob. void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap index 6f18c0a49641c9365d0f950570d9930b7e3e336a..b399f0beee59a1eb18cf011e2380563f4af153ac 100644 --- a/clang/include/module.modulemap +++ b/clang/include/module.modulemap @@ -116,7 +116,6 @@ module Clang_Diagnostics { module Frontend { header "clang/Frontend/FrontendDiagnostic.h" export * } module Lex { header "clang/Lex/LexDiagnostic.h" export * } module Parse { header "clang/Parse/ParseDiagnostic.h" export * } - module Sema { header "clang/Sema/SemaDiagnostic.h" export * } module Serialization { header "clang/Serialization/SerializationDiagnostic.h" export * } module Refactoring { header "clang/Tooling/Refactoring/RefactoringDiagnostic.h" export * } } diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 4d1c698ae6310d559a653c9ebfa074b68d7809e8..a03cef36294dbb49e3a5aeeef3644006dbccb843 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -24,11 +24,10 @@ const uint16_t VERSION_MAJOR = 0; /// API notes file minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t VERSION_MINOR = - 32; // implicit parameter support (at position -1) +const uint16_t VERSION_MINOR = 33; // SwiftEscapable -const uint8_t kSwiftCopyable = 1; -const uint8_t kSwiftNonCopyable = 2; +const uint8_t kSwiftConforms = 1; +const uint8_t kSwiftDoesNotConform = 2; using IdentifierID = llvm::PointerEmbeddedInt; using IdentifierIDField = llvm::BCVBR<16>; diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 0f8fa1355bfb0aba3ce3b2e4002cdb746f14ffef..45a344c13f470efd50e4bd7def73841dd0c0672d 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -589,10 +589,12 @@ public: uint8_t Copyable = endian::readNext(Data); - if (Copyable == kSwiftNonCopyable) - Info.setSwiftCopyable(std::optional(false)); - else if (Copyable == kSwiftCopyable) - Info.setSwiftCopyable(std::optional(true)); + if (Copyable == kSwiftConforms || Copyable == kSwiftDoesNotConform) + Info.setSwiftCopyable(std::optional(Copyable == kSwiftConforms)); + uint8_t Escapable = + endian::readNext(Data); + if (Escapable == kSwiftConforms || Escapable == kSwiftDoesNotConform) + Info.setSwiftEscapable(std::optional(Escapable == kSwiftConforms)); unsigned ImportAsLength = endian::readNext(Data); diff --git a/clang/lib/APINotes/APINotesTypes.cpp b/clang/lib/APINotes/APINotesTypes.cpp index b92faa0acc74821de3cdae09d6c300fbd929bbcf..d06277fa36727416a0a1a744929ed17004fe83c6 100644 --- a/clang/lib/APINotes/APINotesTypes.cpp +++ b/clang/lib/APINotes/APINotesTypes.cpp @@ -104,6 +104,10 @@ LLVM_DUMP_METHOD void TagInfo::dump(llvm::raw_ostream &OS) { if (EnumExtensibility) OS << "Enum Extensibility: " << static_cast(*EnumExtensibility) << ' '; + if (SwiftCopyableSpecified) + OS << (SwiftCopyable ? "[SwiftCopyable] " : "[~SwiftCopyable]"); + if (SwiftEscapableSpecified) + OS << (SwiftEscapable ? "[SwiftEscapable] " : "[~SwiftEscapable]"); OS << '\n'; } diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index 3b8b3c80f7c0866701e843f807d8fd35e6c5d97a..480e1190358d48031919e98d47977e109a8fd7aa 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -1266,11 +1266,13 @@ public: class TagTableInfo : public CommonTypeTableInfo { public: unsigned getUnversionedInfoSize(const TagInfo &TI) { + // clang-format off return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + 2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) + - 2 + getCommonTypeInfoSize(TI); + 3 + getCommonTypeInfoSize(TI); + // clang-format on } void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) { @@ -1289,7 +1291,12 @@ public: writer.write(Flags); if (auto Copyable = TI.isSwiftCopyable()) - writer.write(*Copyable ? kSwiftCopyable : kSwiftNonCopyable); + writer.write(*Copyable ? kSwiftConforms : kSwiftDoesNotConform); + else + writer.write(0); + + if (auto Escapable = TI.isSwiftEscapable()) + writer.write(*Escapable ? kSwiftConforms : kSwiftDoesNotConform); else writer.write(0); diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index e3cb2b3f573886869004159bca59751dc43bf210..0668dda910f2a8faba9568b8e67cbe649f2a66ef 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -459,6 +459,7 @@ struct Tag { std::optional FlagEnum; std::optional EnumConvenienceKind; std::optional SwiftCopyable; + std::optional SwiftEscapable; FunctionsSeq Methods; FieldsSeq Fields; @@ -498,6 +499,7 @@ template <> struct MappingTraits { IO.mapOptional("FlagEnum", T.FlagEnum); IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); + IO.mapOptional("SwiftEscapable", T.SwiftEscapable); IO.mapOptional("Methods", T.Methods); IO.mapOptional("Fields", T.Fields); IO.mapOptional("Tags", T.Tags); @@ -983,6 +985,8 @@ public: if (T.SwiftCopyable) TI.setSwiftCopyable(T.SwiftCopyable); + if (T.SwiftEscapable) + TI.setSwiftEscapable(T.SwiftEscapable); if (T.EnumConvenienceKind) { if (T.EnumExtensibility) { diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index d8efbe44dbecbb2f85d69e9fce67a165a6bcc3e1..bdc713ca3e791eafab1188efb0afb92a9d8a3873 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -14,7 +14,6 @@ #include "clang/AST/ASTConcept.h" #include "clang/AST/ASTContext.h" #include "clang/AST/PrettyPrinter.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" using namespace clang; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index fa0144c5ae59fb6a9905c4a6a675303e3a0ac2ad..2df2730811e68193695084bf664b06535babd47b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -32,7 +32,6 @@ #include "clang/AST/DependenceFlags.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Mangle.h" #include "clang/AST/MangleNumberingContext.h" @@ -41,7 +40,6 @@ #include "clang/AST/RawCommentList.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Stmt.h" -#include "clang/AST/StmtOpenACC.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -81,7 +79,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/Support/Capacity.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" @@ -11465,7 +11462,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, Qualifiers RHSPteeQual = RHSPointee.getQualifiers(); // Blocks can't be an expression in a ternary operator (OpenCL v2.0 // 6.12.5) thus the following check is asymmetric. - if (!LHSPteeQual.isAddressSpaceSupersetOf(RHSPteeQual)) + if (!LHSPteeQual.isAddressSpaceSupersetOf(RHSPteeQual, *this)) return {}; LHSPteeQual.removeAddressSpace(); RHSPteeQual.removeAddressSpace(); @@ -14387,11 +14384,13 @@ QualType ASTContext::getCorrespondingSignedFixedPointType(QualType Ty) const { // corresponding backend features (which may contain duplicates). static std::vector getFMVBackendFeaturesFor( const llvm::SmallVectorImpl &FMVFeatStrings) { - std::vector BackendFeats; + std::vector BackendFeats{{"+fmv"}}; + llvm::AArch64::ExtensionSet FeatureBits; for (StringRef F : FMVFeatStrings) if (auto FMVExt = llvm::AArch64::parseFMVExtension(F)) - for (StringRef F : FMVExt->getImpliedFeatures()) - BackendFeats.push_back(F.str()); + if (FMVExt->ID) + FeatureBits.enable(*FMVExt->ID); + FeatureBits.toLLVMFeatureList(BackendFeats); return BackendFeats; } diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 864d0393f9a78ee57648c4ec4590785a64585aee..5e4487e0687d329abc716cdbe8123592c44a95e1 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -16,7 +16,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclLookups.h" #include "clang/AST/JSONNodeDumper.h" -#include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 35aba41f0052afc69a76ddfa3844acfad4227992..baed1416635432a1e5f8efa58ce2832acb931af5 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -53,13 +53,11 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" -#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 120ddc0f26c0d7951b23aa41ff936daeafb760f6..308551c30615107a260f10e8d3be883651af4992 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -86,7 +86,6 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include @@ -2303,7 +2302,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // Check whether we already know that these two declarations are not // structurally equivalent. - if (Context.NonEquivalentDecls.count(P)) + if (Context.NonEquivalentDecls.count( + std::make_tuple(D1, D2, Context.IgnoreTemplateParmDepth))) return false; // Check if a check for these declarations is already pending. @@ -2511,7 +2511,8 @@ bool StructuralEquivalenceContext::Finish() { if (!Equivalent) { // Note that these two declarations are not equivalent (and we already // know about it). - NonEquivalentDecls.insert(P); + NonEquivalentDecls.insert( + std::make_tuple(D1, D2, IgnoreTemplateParmDepth)); return true; } diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp index 4fd697ebe4938d1736db67788b17e58a1efea4a3..3f2bc46664a4ae9747d8368041a648d1daa858da 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp @@ -8,7 +8,6 @@ #include "ByteCodeEmitter.h" #include "Context.h" -#include "FixedPoint.h" #include "Floating.h" #include "IntegralAP.h" #include "Opcode.h" @@ -16,7 +15,6 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" -#include "clang/Basic/Builtins.h" #include using namespace clang; diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp b/clang/lib/AST/ByteCode/Descriptor.cpp index 39a54e4902cd2ab1d673f35f5fdc0d67cd809d00..437b9f1bab2d6a20d870f19dbbf4a8e06fafb7bf 100644 --- a/clang/lib/AST/ByteCode/Descriptor.cpp +++ b/clang/lib/AST/ByteCode/Descriptor.cpp @@ -10,7 +10,6 @@ #include "Boolean.h" #include "FixedPoint.h" #include "Floating.h" -#include "FunctionPointer.h" #include "IntegralAP.h" #include "MemberPointer.h" #include "Pointer.h" diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp index 65ad960cfa8d21640eefee8ef5ed98c041a797da..9763fe89b7374285b8e79bf503744af437288250 100644 --- a/clang/lib/AST/ByteCode/EvalEmitter.cpp +++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp @@ -10,7 +10,6 @@ #include "Context.h" #include "IntegralAP.h" #include "Interp.h" -#include "Opcode.h" #include "clang/AST/DeclCXX.h" using namespace clang; diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp index c0d116cdf26c48435400794c3f6b2b947119b52a..0ce8f15ea9127ca7c628b209b5e397a1c4b5ea71 100644 --- a/clang/lib/AST/ByteCode/EvaluationResult.cpp +++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp @@ -9,7 +9,6 @@ #include "EvaluationResult.h" #include "InterpState.h" #include "Record.h" -#include "clang/AST/ExprCXX.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include diff --git a/clang/lib/AST/ByteCode/Function.cpp b/clang/lib/AST/ByteCode/Function.cpp index 52d6d05211f64262e54c8c1ed8026716a15a9826..896a4fb3f9469ae2f1214f8f554497d5beb3ae3f 100644 --- a/clang/lib/AST/ByteCode/Function.cpp +++ b/clang/lib/AST/ByteCode/Function.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "Function.h" -#include "Opcode.h" #include "Program.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 0e571624ae18d16e9342a6eab0dfbcbff190dca6..339af0c873a8e49a4d5f376baae02a6d075652b1 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -16,17 +16,13 @@ #include "Program.h" #include "State.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/APSInt.h" #include "llvm/ADT/StringExtras.h" -#include -#include using namespace clang; using namespace clang::interp; diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp index 17a175a48b5df4d90b486bcafde9b11a682dbda6..b1230f92ddf1d49d9eff64dedb46080d41634c1c 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp @@ -8,10 +8,8 @@ #include "InterpBuiltinBitCast.h" #include "Boolean.h" #include "Context.h" -#include "FixedPoint.h" #include "Floating.h" #include "Integral.h" -#include "IntegralAP.h" #include "InterpState.h" #include "MemberPointer.h" #include "Pointer.h" @@ -19,8 +17,6 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/BitVector.h" -#include using namespace clang; using namespace clang::interp; @@ -258,7 +254,7 @@ static bool CheckBitcastType(InterpState &S, CodePtr OpPC, QualType T, }; auto note = [&](int Construct, QualType NoteType, SourceRange NoteRange) { S.Note(NoteRange.getBegin(), diag::note_constexpr_bit_cast_invalid_subtype) - << NoteType << Construct << T << NoteRange; + << NoteType << Construct << T.getUnqualifiedType() << NoteRange; return false; }; @@ -392,11 +388,10 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC, QualType FromType = FromPtr.getType(); QualType ToType = ToPtr.getType(); - if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false)) - return false; - if (!CheckBitcastType(S, OpPC, ToType, /*IsToType=*/true)) return false; + if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false)) + return false; BitcastBuffer Buffer; readPointerToBuffer(S.getContext(), FromPtr, Buffer, diff --git a/clang/lib/AST/ByteCode/PrimType.cpp b/clang/lib/AST/ByteCode/PrimType.cpp index 7dbab996416cc3bbd49092233ea26163689aa3b3..b4c1fd03055405a12a68ec615b6bc24db2945094 100644 --- a/clang/lib/AST/ByteCode/PrimType.cpp +++ b/clang/lib/AST/ByteCode/PrimType.cpp @@ -10,7 +10,6 @@ #include "Boolean.h" #include "FixedPoint.h" #include "Floating.h" -#include "FunctionPointer.h" #include "IntegralAP.h" #include "MemberPointer.h" #include "Pointer.h" diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 04e0b1884e3d6be8128aacecaf20c62898b4ab36..590ee19de6d2f08f10d7bd38f85b3e07b3dabea8 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -10,7 +10,6 @@ #include "Context.h" #include "Function.h" #include "Integral.h" -#include "Opcode.h" #include "PrimType.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" diff --git a/clang/lib/AST/ByteCode/Source.cpp b/clang/lib/AST/ByteCode/Source.cpp index 55296ddd8c5583cd95320908202fe415a57c067d..d4ce7537f3d244f1625d22927b790ee7769d4a44 100644 --- a/clang/lib/AST/ByteCode/Source.cpp +++ b/clang/lib/AST/ByteCode/Source.cpp @@ -33,7 +33,7 @@ SourceRange SourceInfo::getRange() const { } const Expr *SourceInfo::asExpr() const { - if (const auto *S = dyn_cast(Source)) + if (const auto *S = dyn_cast_if_present(Source)) return dyn_cast(S); return nullptr; } diff --git a/clang/lib/AST/ByteCode/Source.h b/clang/lib/AST/ByteCode/Source.h index 3b025535d00b19be76cc70529d8cf63ef312dcd7..c74cda919347c05128c1175b85d37e877c9bf2b0 100644 --- a/clang/lib/AST/ByteCode/Source.h +++ b/clang/lib/AST/ByteCode/Source.h @@ -83,8 +83,12 @@ public: SourceLocation getLoc() const; SourceRange getRange() const; - const Stmt *asStmt() const { return dyn_cast(Source); } - const Decl *asDecl() const { return dyn_cast(Source); } + const Stmt *asStmt() const { + return dyn_cast_if_present(Source); + } + const Decl *asDecl() const { + return dyn_cast_if_present(Source); + } const Expr *asExpr() const; operator bool() const { return !Source.isNull(); } diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index eb265a872c1259f38f300a35591899d0aaa9cd65..aefc06e9197cfbc0d32c78b5b7746d1c22f7e72b 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -24,10 +24,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/Support/Casting.h" #include -#include #include +#include #include using namespace clang; diff --git a/clang/lib/AST/CommentCommandTraits.cpp b/clang/lib/AST/CommentCommandTraits.cpp index a37a0e18432cbe3b70d2a45afdc71b6e7e8f356d..c83392b637540a465ae041b17a8b93a9bee7f474 100644 --- a/clang/lib/AST/CommentCommandTraits.cpp +++ b/clang/lib/AST/CommentCommandTraits.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "clang/AST/CommentCommandTraits.h" -#include "llvm/ADT/STLExtras.h" #include namespace clang { diff --git a/clang/lib/AST/CommentSema.cpp b/clang/lib/AST/CommentSema.cpp index bc01baa1d917b578bc0b14638bb803b6a8466a54..69eda00643a8fa237553340f32f7127bbcb518f8 100644 --- a/clang/lib/AST/CommentSema.cpp +++ b/clang/lib/AST/CommentSema.cpp @@ -15,7 +15,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" namespace clang { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5de9cb4b9ec56b6bed4adf3264ec799a4bba98e8..38fdb49514fbbbcc7eea0f660acd60be28d034b0 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -21,7 +21,6 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 48b91dca1f6d91ff2231719e978a6647d342ea58..96638b85c452b4e137e2dc36d84966102688186b 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -34,11 +34,8 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/VersionTuple.h" diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 4394a0724b3c17c877d061fe2085bac289a62761..39c548e9c22539ab18b5105e422319b317371425 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -33,7 +33,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" diff --git a/clang/lib/AST/DeclFriend.cpp b/clang/lib/AST/DeclFriend.cpp index 8b285bfce8d522180c0862aca8a3ab816fe6f1e9..d003842bfb7c74f56d909858cd4265670818583e 100644 --- a/clang/lib/AST/DeclFriend.cpp +++ b/clang/lib/AST/DeclFriend.cpp @@ -12,13 +12,12 @@ //===----------------------------------------------------------------------===// #include "clang/AST/DeclFriend.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/LLVM.h" -#include "llvm/Support/Casting.h" #include #include diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index ae8a310769260ce314c87d43e1f6d49f29cdfe93..5c107325df30c660163600d8ad52d68aa5aaba95 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -24,9 +24,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index a221d619672b388dd50181370bb3460d714ecad2..f487032a37ab733da130ec7aaa1fa4fe617fbace 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -29,11 +29,8 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" -#include #include -#include #include #include #include diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index a3ac5551e0cc2412e20b8da89c040362dc7afb27..ae5fcf6e86adfcf4010f5e48ca99f3e9544ddd83 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -28,13 +28,11 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include #include -#include #include using namespace clang; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index bf2c1b92fa6b49b4e996ca241151a2088a0302b0..a4fb4d5a1f2ec419c5875c22fc0feba1e6f19a42 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -25,7 +25,6 @@ #include "clang/AST/IgnoreExpr.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" @@ -1616,22 +1615,24 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { return FnType->getReturnType(); } -const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { +std::pair +CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { + // If the callee is marked nodiscard, return that attribute + const Decl *D = getCalleeDecl(); + if (const auto *A = D->getAttr()) + return {nullptr, A}; + // If the return type is a struct, union, or enum that is marked nodiscard, // then return the return type attribute. if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl()) if (const auto *A = TD->getAttr()) - return A; + return {TD, A}; for (const auto *TD = getCallReturnType(Ctx)->getAs(); TD; TD = TD->desugar()->getAs()) if (const auto *A = TD->getDecl()->getAttr()) - return A; - - // Otherwise, see if the callee is marked nodiscard and return that attribute - // instead. - const Decl *D = getCalleeDecl(); - return D ? D->getAttr() : nullptr; + return {TD->getDecl(), A}; + return {nullptr, nullptr}; } SourceLocation CallExpr::getBeginLoc() const { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index a2c0c60d43dd14c76ad716ce9dc6e41650371a0a..0ce129de85f03fb17c9f693c99fee40df0f8d8fd 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -32,7 +32,6 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include #include diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp index 0704630c0fc266400e2f432db5b7eab2a06aa2f0..6efe73ea085a79dcaf194994d270bc0eec27fd3f 100644 --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -23,10 +23,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/Support/TrailingObjects.h" #include -#include -#include using namespace clang; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d664c503655ba6b8e959814c52f11647aca941ab..33206f5cda2021a17a9a81adcd67311d843eb437 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -38,7 +38,6 @@ #include "ExprConstShared.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" @@ -13528,6 +13527,43 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(DidOverflow, E); } + case Builtin::BI__builtin_reduce_add: + case Builtin::BI__builtin_reduce_mul: + case Builtin::BI__builtin_reduce_and: { + APValue Source; + if (!EvaluateAsRValue(Info, E->getArg(0), Source)) + return false; + + unsigned SourceLen = Source.getVectorLength(); + APSInt Reduced = Source.getVectorElt(0).getInt(); + for (unsigned EltNum = 1; EltNum < SourceLen; ++EltNum) { + switch (BuiltinOp) { + default: + return false; + case Builtin::BI__builtin_reduce_add: { + if (!CheckedIntArithmetic( + Info, E, Reduced, Source.getVectorElt(EltNum).getInt(), + Reduced.getBitWidth() + 1, std::plus(), Reduced)) + return false; + break; + } + case Builtin::BI__builtin_reduce_mul: { + if (!CheckedIntArithmetic( + Info, E, Reduced, Source.getVectorElt(EltNum).getInt(), + Reduced.getBitWidth() * 2, std::multiplies(), Reduced)) + return false; + break; + } + case Builtin::BI__builtin_reduce_and: { + Reduced &= Source.getVectorElt(EltNum).getInt(); + break; + } + } + } + + return Success(Reduced, E); + } + case clang::X86::BI__builtin_ia32_addcarryx_u32: case clang::X86::BI__builtin_ia32_addcarryx_u64: case clang::X86::BI__builtin_ia32_subborrow_u32: diff --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp index a3222c2da24fd4e081e7e38ab6cbb866fafe21bb..79b5db301d414792936450cf08c9db4de209c592 100644 --- a/clang/lib/AST/ExprObjC.cpp +++ b/clang/lib/AST/ExprObjC.cpp @@ -13,11 +13,9 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ComputeDependence.h" -#include "clang/AST/DependenceFlags.h" #include "clang/AST/SelectorLocationsKind.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ErrorHandling.h" #include #include diff --git a/clang/lib/AST/ExternalASTSource.cpp b/clang/lib/AST/ExternalASTSource.cpp index a5b6f80bde694c2a4fcd9127cf1f0c8f6aec3cbe..7a14cc7d50ed0564878885784631e0680c2ca79d 100644 --- a/clang/lib/AST/ExternalASTSource.cpp +++ b/clang/lib/AST/ExternalASTSource.cpp @@ -16,10 +16,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclarationName.h" #include "clang/Basic/ASTSourceDescriptor.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/SourceManager.h" #include "llvm/Support/ErrorHandling.h" #include #include diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index c9aadce73141249d8123705c49b1af00572ee847..bf152ca35431cd0f7e30be43306e8141cce1aaab 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -24,7 +24,6 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/iterator.h" #include diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 14bc260d0245fb90e6d981ebe2b7a2c94ef54a1a..27a993a631dae9c0050830333914c47b154f9b3a 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -28,9 +28,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/ABI.h" -#include "clang/Basic/DiagnosticAST.h" #include "clang/Basic/Module.h" -#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Thunk.h" #include "llvm/ADT/StringExtras.h" diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 4875e8537b3c11f1951d7404cf2af63c9c3e6e80..15be9c62bf888055f68f6b63ea6893e9321dad58 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -9,17 +9,16 @@ // Implements generic name mangling support for blocks and Objective-C. // //===----------------------------------------------------------------------===// -#include "clang/AST/Attr.h" +#include "clang/AST/Mangle.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/Mangle.h" #include "clang/AST/VTableBuilder.h" #include "clang/Basic/ABI.h" -#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index dbc161347025c0df7d9bbc0abf4d97c334d62548..94a7ce6c1321d3b55d2c013d09237ba5ed9f99bc 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -26,14 +26,12 @@ #include "clang/AST/VTableBuilder.h" #include "clang/Basic/ABI.h" #include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CRC.h" #include "llvm/Support/MD5.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/xxhash.h" #include diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index 785c46e86a77c57de82240343a39205d64079593..76c77569da9fda673429c3435d0b8116aa756c8b 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -25,8 +25,6 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 1929314363817ac64800d69f4e06831a1b4de41c..645ca6f0e7b715bf6424115ebfe6f2ac17e4e42a 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -16,7 +16,6 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeVisitor.h" using namespace clang; diff --git a/clang/lib/AST/OSLog.cpp b/clang/lib/AST/OSLog.cpp index 5e320416b30df678d273bd2454028db75b09de70..b777d4d65b84d60f2a5124f704d419e733cb8fac 100644 --- a/clang/lib/AST/OSLog.cpp +++ b/clang/lib/AST/OSLog.cpp @@ -7,7 +7,6 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/FormatString.h" #include "clang/Basic/Builtins.h" -#include "llvm/ADT/SmallBitVector.h" #include using namespace clang; diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 5efa6ececf2c190ac1b3ff28243b1b80bb313a0c..6bcef8760152094d146da13beb877a3e76529b39 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -19,7 +19,6 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include #include diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp index e97cb5e226f5c28ecf841cab05fe8cc3fda73a10..fd749b02b758c9ec1879889ff093a39bc6e389af 100644 --- a/clang/lib/AST/ParentMap.cpp +++ b/clang/lib/AST/ParentMap.cpp @@ -13,7 +13,6 @@ #include "clang/AST/ParentMap.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" #include "llvm/ADT/DenseMap.h" diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 4e1243ef79e871390bddcced8b66a78ba751fcbe..e4d2a6937f6eb6e850febe2ffc5d8c2fe661f763 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -6,14 +6,10 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/QualTypeNames.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/GlobalDecl.h" #include "clang/AST/Mangle.h" -#include "clang/AST/QualTypeNames.h" - -#include -#include namespace clang { diff --git a/clang/lib/AST/Randstruct.cpp b/clang/lib/AST/Randstruct.cpp index 99c665f420e664b3f3884f901a7dad84dd3a4ae0..b484afa4997bbc3baead8e5543d21b0674d9f7de 100644 --- a/clang/lib/AST/Randstruct.cpp +++ b/clang/lib/AST/Randstruct.cpp @@ -13,7 +13,6 @@ #include "clang/AST/Randstruct.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" // For StaticAssertDecl @@ -23,7 +22,6 @@ #include #include #include -#include #include using clang::ASTContext; diff --git a/clang/lib/AST/RawCommentList.cpp b/clang/lib/AST/RawCommentList.cpp index dffa007b6588bc05895f2789532d0f23c4586b5b..fddedd3a31856a3dd9c66378717ffca010c6c901 100644 --- a/clang/lib/AST/RawCommentList.cpp +++ b/clang/lib/AST/RawCommentList.cpp @@ -15,8 +15,6 @@ #include "clang/AST/CommentParser.h" #include "clang/AST/CommentSema.h" #include "clang/Basic/CharInfo.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Allocator.h" using namespace clang; diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index d9bf62c2bbb04a56afeac66aa5ed43fec9319f72..b1b13b66a5e504573d1459be771c643da37fdb10 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -14,10 +14,9 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" -#include "clang/AST/VTableBuilder.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index fe59d6070b3e811917336a855399df209451eac9..1e527ed0b2a2ea898f812fdddc3115cd042b263d 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -34,7 +34,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -44,7 +43,6 @@ #include #include #include -#include #include using namespace clang; diff --git a/clang/lib/AST/StmtIterator.cpp b/clang/lib/AST/StmtIterator.cpp index 70c8dc94e2df67b3c8db999b58de248ce7f72298..760522929b42d7a152162698f32528e260705b3b 100644 --- a/clang/lib/AST/StmtIterator.cpp +++ b/clang/lib/AST/StmtIterator.cpp @@ -14,7 +14,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" -#include "llvm/Support/Casting.h" #include #include diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp index 82125538acaaa7c8f2ee1921e484904d275b9515..23dd57d235813afa96370822d936106ace2620f1 100644 --- a/clang/lib/AST/StmtOpenACC.cpp +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -12,7 +12,6 @@ #include "clang/AST/StmtOpenACC.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" using namespace clang; @@ -89,3 +88,25 @@ OpenACCLoopConstruct *OpenACCLoopConstruct::Create( OpenACCLoopConstruct(ParentKind, BeginLoc, DirLoc, EndLoc, Clauses, Loop); return Inst; } + +OpenACCCombinedConstruct * +OpenACCCombinedConstruct::CreateEmpty(const ASTContext &C, + unsigned NumClauses) { + void *Mem = C.Allocate( + OpenACCCombinedConstruct::totalSizeToAlloc( + NumClauses)); + auto *Inst = new (Mem) OpenACCCombinedConstruct(NumClauses); + return Inst; +} + +OpenACCCombinedConstruct *OpenACCCombinedConstruct::Create( + const ASTContext &C, OpenACCDirectiveKind DK, SourceLocation BeginLoc, + SourceLocation DirLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *Loop) { + void *Mem = C.Allocate( + OpenACCCombinedConstruct::totalSizeToAlloc( + Clauses.size())); + auto *Inst = new (Mem) + OpenACCCombinedConstruct(DK, BeginLoc, DirLoc, EndLoc, Clauses, Loop); + return Inst; +} diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 8fd985ee3943ef49f68b034c7aa30cc9b1e19f3b..7e465e610c1a750aef97d4247452914636f939cf 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -33,7 +33,6 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" -#include "clang/Basic/CharInfo.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/JsonSupport.h" @@ -45,11 +44,9 @@ #include "clang/Basic/TypeTraits.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -1229,6 +1226,18 @@ void StmtPrinter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) { PrintStmt(S->getLoop()); } +void StmtPrinter::VisitOpenACCCombinedConstruct(OpenACCCombinedConstruct *S) { + Indent() << "#pragma acc " << S->getDirectiveKind(); + if (!S->clauses().empty()) { + OS << ' '; + OpenACCClausePrinter Printer(OS, Policy); + Printer.VisitClauseList(S->clauses()); + } + OS << '\n'; + + PrintStmt(S->getLoop()); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index eba8970972cb903a8dd9aec67fea2db8d4134688..5e266bc185f7326bf1f8cd92b7c2c098e53fa0c2 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2759,6 +2759,15 @@ void StmtProfiler::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) { P.VisitOpenACCClauseList(S->clauses()); } +void StmtProfiler::VisitOpenACCCombinedConstruct( + const OpenACCCombinedConstruct *S) { + // VisitStmt handles children, so the Loop is handled. + VisitStmt(S); + + OpenACCClauseProfiler P{*this}; + P.VisitOpenACCClauseList(S->clauses()); +} + void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) { VisitStmt(S); } diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 2e6839e948d9d3c99d54f16992d0c0895f4e352d..3625b6e435a5566dd729fe593c531a5a13c8b138 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -29,10 +29,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index c27b07ad6c6f8788dd756778630f0235869fd0ac..c500507fecdf59b950ced84f4014abb216d3c29b 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -25,7 +25,6 @@ #include "clang/Basic/OperatorKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index ac4cb99db0561a61765089041d3588d43c1fbed7..995d2b886d1293dfbe5a2d8255456dfb89a1157f 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -2934,6 +2934,11 @@ void TextNodeDumper::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) { OS << " parent: " << S->getParentComputeConstructKind(); } +void TextNodeDumper::VisitOpenACCCombinedConstruct( + const OpenACCCombinedConstruct *S) { + OS << " " << S->getDirectiveKind(); +} + void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) { AddChild("begin", [=] { OS << S->getStartingElementPos(); }); AddChild("number of elements", [=] { OS << S->getDataElementCount(); }); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 7de13977176f2d5a4e87fe748e30113daeb493c6..b70f86ef31442ddafdc85983bf814756f6ca9f95 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -24,7 +24,6 @@ #include "clang/AST/DependenceFlags.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" @@ -45,16 +44,13 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" -#include "llvm/TargetParser/RISCVTargetParser.h" #include #include #include #include #include -#include using namespace clang; @@ -73,6 +69,36 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const { (hasObjCLifetime() && !Other.hasObjCLifetime())); } +bool Qualifiers::isTargetAddressSpaceSupersetOf(LangAS A, LangAS B, + const ASTContext &Ctx) { + // In OpenCLC v2.0 s6.5.5: every address space except for __constant can be + // used as __generic. + return (A == LangAS::opencl_generic && B != LangAS::opencl_constant) || + // We also define global_device and global_host address spaces, + // to distinguish global pointers allocated on host from pointers + // allocated on device, which are a subset of __global. + (A == LangAS::opencl_global && (B == LangAS::opencl_global_device || + B == LangAS::opencl_global_host)) || + (A == LangAS::sycl_global && + (B == LangAS::sycl_global_device || B == LangAS::sycl_global_host)) || + // Consider pointer size address spaces to be equivalent to default. + ((isPtrSizeAddressSpace(A) || A == LangAS::Default) && + (isPtrSizeAddressSpace(B) || B == LangAS::Default)) || + // Default is a superset of SYCL address spaces. + (A == LangAS::Default && + (B == LangAS::sycl_private || B == LangAS::sycl_local || + B == LangAS::sycl_global || B == LangAS::sycl_global_device || + B == LangAS::sycl_global_host)) || + // In HIP device compilation, any cuda address space is allowed + // to implicitly cast into the default address space. + (A == LangAS::Default && + (B == LangAS::cuda_constant || B == LangAS::cuda_device || + B == LangAS::cuda_shared)) || + // Conversions from target specific address spaces may be legal + // depending on the target information. + Ctx.getTargetInfo().isAddressSpaceSupersetOf(A, B); +} + const IdentifierInfo* QualType::getBaseTypeIdentifier() const { const Type* ty = getTypePtr(); NamedDecl *ND = nullptr; diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 5c08769aa20513384eca2b4634b5c00a575644d4..f28f420fcb010289cdc1745b2c09287addb6db7f 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -22,9 +22,9 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" -#include "clang/AST/TextNodeDumper.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/AttrKinds.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" @@ -37,7 +37,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" @@ -1958,6 +1957,14 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, OS << " [[clang::lifetimebound]]"; return; } + if (T->getAttrKind() == attr::LifetimeCaptureBy) { + OS << " [[clang::lifetime_capture_by("; + if (auto *attr = dyn_cast_or_null(T->getAttr())) + llvm::interleaveComma(attr->getArgIdents(), OS, + [&](auto it) { OS << it->getName(); }); + OS << ")]]"; + return; + } // The printing of the address_space attribute is handled by the qualifier // since it is still stored in the qualifier. Return early to prevent printing @@ -2025,6 +2032,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::SizedBy: case attr::SizedByOrNull: case attr::LifetimeBound: + case attr::LifetimeCaptureBy: case attr::TypeNonNull: case attr::TypeNullable: case attr::TypeNullableResult: diff --git a/clang/lib/AST/VTTBuilder.cpp b/clang/lib/AST/VTTBuilder.cpp index 464a2014c430a04f554b49165a39ec415523ead2..de011848a721e3032c8fdf42eca7c88ea1afef76 100644 --- a/clang/lib/AST/VTTBuilder.cpp +++ b/clang/lib/AST/VTTBuilder.cpp @@ -20,7 +20,6 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" -#include "llvm/Support/Casting.h" #include #include diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index f678ac6f2ff36a7fd999afe72333cf1479a86590..304bbb2b422c61d9cba416d7712ca60ab365f5d0 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -760,6 +760,7 @@ private: void cleanupConstructionContext(Expr *E); void autoCreateBlock() { if (!Block) Block = createBlock(); } + CFGBlock *createBlock(bool add_successor = true); CFGBlock *createNoReturnBlock(); @@ -818,15 +819,21 @@ private: B->appendStmt(const_cast(S), cfg->getBumpVectorContext()); } - void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) { + void appendConstructor(CXXConstructExpr *CE) { + CXXConstructorDecl *C = CE->getConstructor(); + if (C && C->isNoReturn()) + Block = createNoReturnBlock(); + else + autoCreateBlock(); + if (const ConstructionContext *CC = retrieveAndCleanupConstructionContext(CE)) { - B->appendConstructor(CE, CC, cfg->getBumpVectorContext()); + Block->appendConstructor(CE, CC, cfg->getBumpVectorContext()); return; } // No valid construction context found. Fall back to statement. - B->appendStmt(CE, cfg->getBumpVectorContext()); + Block->appendStmt(CE, cfg->getBumpVectorContext()); } void appendCall(CFGBlock *B, CallExpr *CE) { @@ -3177,11 +3184,14 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { if (!I->isConsteval()) KnownVal = tryEvaluateBool(I->getCond()); - // Add the successors. If we know that specific branches are + // Add the successors. If we know that specific branches are // unreachable, inform addSuccessor() of that knowledge. addSuccessor(Block, ThenBlock, /* IsReachable = */ !KnownVal.isFalse()); addSuccessor(Block, ElseBlock, /* IsReachable = */ !KnownVal.isTrue()); + if (I->isConsteval()) + return Block; + // Add the condition as the last statement in the new block. This may // create new blocks as the condition may contain control-flow. Any newly // created blocks will be pointed to be "Block". @@ -4829,9 +4839,7 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C, // construct these objects. Construction contexts we find here aren't for the // constructor C, they're for its arguments only. findConstructionContextsForArguments(C); - - autoCreateBlock(); - appendConstructor(Block, C); + appendConstructor(C); return VisitChildren(C); } @@ -4889,16 +4897,15 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E, return Visit(E->getSubExpr(), asc); } -CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C, +CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E, AddStmtChoice asc) { // If the constructor takes objects as arguments by value, we need to properly // construct these objects. Construction contexts we find here aren't for the // constructor C, they're for its arguments only. - findConstructionContextsForArguments(C); + findConstructionContextsForArguments(E); + appendConstructor(E); - autoCreateBlock(); - appendConstructor(Block, C); - return VisitChildren(C); + return VisitChildren(E); } CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E, diff --git a/clang/lib/Analysis/CallGraph.cpp b/clang/lib/Analysis/CallGraph.cpp index f892980ed31386b1c6e27b085c7716b6fd856250..d9da74d40efff6c223d661d1fdf091c6cff81f5c 100644 --- a/clang/lib/Analysis/CallGraph.cpp +++ b/clang/lib/Analysis/CallGraph.cpp @@ -147,6 +147,9 @@ void CallGraph::addNodesForBlocks(DeclContext *D) { } CallGraph::CallGraph() { + ShouldWalkTypesOfTypeLocs = false; + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; Root = getOrInsertNode(nullptr); } diff --git a/clang/lib/Analysis/CalledOnceCheck.cpp b/clang/lib/Analysis/CalledOnceCheck.cpp index 30cbd257b65e8fd388b6fba09350200ff09df66d..1554eab1860c1575e901ef4b916f328458618eab 100644 --- a/clang/lib/Analysis/CalledOnceCheck.cpp +++ b/clang/lib/Analysis/CalledOnceCheck.cpp @@ -11,11 +11,11 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" @@ -426,7 +426,7 @@ const Expr *getCondition(const Stmt *S) { /// of the AST will end up in the results. /// Results might have duplicate names, if this is a problem, convert to /// string sets afterwards. -class NamesCollector : public RecursiveASTVisitor { +class NamesCollector : public DynamicRecursiveASTVisitor { public: static constexpr unsigned EXPECTED_NUMBER_OF_NAMES = 5; using NameCollection = @@ -438,12 +438,12 @@ public: return Impl.Result; } - bool VisitDeclRefExpr(const DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { Result.push_back(E->getDecl()->getName()); return true; } - bool VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *E) { + bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) override { llvm::StringRef Name; if (E->isImplicitProperty()) { diff --git a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp index fdba139628d8ff05805ebe5fbd932d79a2bc4bbe..9e7821bfc1e89e4913f5fe2c43365dfa0b5a7c86 100644 --- a/clang/lib/Analysis/FlowSensitive/ASTOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/ASTOps.cpp @@ -198,13 +198,12 @@ static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { return nullptr; } -class ReferencedDeclsVisitor - : public AnalysisASTVisitor { +class ReferencedDeclsVisitor : public AnalysisASTVisitor { public: ReferencedDeclsVisitor(ReferencedDecls &Referenced) : Referenced(Referenced) {} - void TraverseConstructorInits(const CXXConstructorDecl *Ctor) { + void traverseConstructorInits(const CXXConstructorDecl *Ctor) { for (const CXXCtorInitializer *Init : Ctor->inits()) { if (Init->isMemberInitializer()) { Referenced.Fields.insert(Init->getMember()); @@ -225,21 +224,21 @@ public: } } - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { insertIfGlobal(*D, Referenced.Globals); insertIfLocal(*D, Referenced.Locals); insertIfFunction(*D, Referenced.Functions); return true; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { insertIfGlobal(*E->getDecl(), Referenced.Globals); insertIfLocal(*E->getDecl(), Referenced.Locals); insertIfFunction(*E->getDecl(), Referenced.Functions); return true; } - bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) { + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *C) override { // If this is a method that returns a member variable but does nothing else, // model the field of the return value. if (MemberExpr *E = getMemberForAccessor(*C)) @@ -248,7 +247,7 @@ public: return true; } - bool VisitMemberExpr(MemberExpr *E) { + bool VisitMemberExpr(MemberExpr *E) override { // FIXME: should we be using `E->getFoundDecl()`? const ValueDecl *VD = E->getMemberDecl(); insertIfGlobal(*VD, Referenced.Globals); @@ -258,14 +257,14 @@ public: return true; } - bool VisitInitListExpr(InitListExpr *InitList) { + bool VisitInitListExpr(InitListExpr *InitList) override { if (InitList->getType()->isRecordType()) for (const auto *FD : getFieldsForInitListExpr(InitList)) Referenced.Fields.insert(FD); return true; } - bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) { + bool VisitCXXParenListInitExpr(CXXParenListInitExpr *ParenInitList) override { if (ParenInitList->getType()->isRecordType()) for (const auto *FD : getFieldsForInitListExpr(ParenInitList)) Referenced.Fields.insert(FD); @@ -281,7 +280,7 @@ ReferencedDecls getReferencedDecls(const FunctionDecl &FD) { ReferencedDeclsVisitor Visitor(Result); Visitor.TraverseStmt(FD.getBody()); if (const auto *CtorDecl = dyn_cast(&FD)) - Visitor.TraverseConstructorInits(CtorDecl); + Visitor.traverseConstructorInits(CtorDecl); return Result; } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index e1f68e493f3553cdb3aa4fe9416b13ad17722aa9..c5c6e900b797666c310afbae488695e31031430a 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -298,7 +298,7 @@ namespace { // Visitor that builds a map from record prvalues to result objects. // For each result object that it encounters, it propagates the storage location // of the result object to all record prvalues that can initialize it. -class ResultObjectVisitor : public AnalysisASTVisitor { +class ResultObjectVisitor : public AnalysisASTVisitor { public: // `ResultObjectMap` will be filled with a map from record prvalues to result // object. If this visitor will traverse a function that returns a record by @@ -315,7 +315,7 @@ public: // called by `RecursiveASTVisitor`; it should be called manually if we are // analyzing a constructor. `ThisPointeeLoc` is the storage location that // `this` points to. - void TraverseConstructorInits(const CXXConstructorDecl *Ctor, + void traverseConstructorInits(const CXXConstructorDecl *Ctor, RecordStorageLocation *ThisPointeeLoc) { assert(ThisPointeeLoc != nullptr); for (const CXXCtorInitializer *Init : Ctor->inits()) { @@ -339,7 +339,7 @@ public: } } - bool VisitVarDecl(VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { if (VD->getType()->isRecordType() && VD->hasInit()) PropagateResultObject( VD->getInit(), @@ -347,7 +347,7 @@ public: return true; } - bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) { + bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) override { if (MTE->getType()->isRecordType()) PropagateResultObject( MTE->getSubExpr(), @@ -355,7 +355,7 @@ public: return true; } - bool VisitReturnStmt(ReturnStmt *Return) { + bool VisitReturnStmt(ReturnStmt *Return) override { Expr *RetValue = Return->getRetValue(); if (RetValue != nullptr && RetValue->getType()->isRecordType() && RetValue->isPRValue()) @@ -363,7 +363,7 @@ public: return true; } - bool VisitExpr(Expr *E) { + bool VisitExpr(Expr *E) override { // Clang's AST can have record-type prvalues without a result object -- for // example as full-expressions contained in a compound statement or as // arguments of call expressions. We notice this if we get here and a @@ -1211,7 +1211,7 @@ Environment::PrValueToResultObject Environment::buildResultObjectMap( ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); if (const auto *Ctor = dyn_cast(FuncDecl)) - Visitor.TraverseConstructorInits(Ctor, ThisPointeeLoc); + Visitor.traverseConstructorInits(Ctor, ThisPointeeLoc); return Map; } diff --git a/clang/lib/Analysis/ProgramPoint.cpp b/clang/lib/Analysis/ProgramPoint.cpp index 768345c8425f025fd6bec1b4339fd046dcfc8f7c..7945c5c2fc27fc68a3703dd72ae6a4a201b131e0 100644 --- a/clang/lib/Analysis/ProgramPoint.cpp +++ b/clang/lib/Analysis/ProgramPoint.cpp @@ -13,6 +13,7 @@ #include "clang/Analysis/ProgramPoint.h" #include "clang/AST/ASTContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/JsonSupport.h" using namespace clang; @@ -81,7 +82,10 @@ void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const { llvm_unreachable("BlockExitKind"); break; case ProgramPoint::CallEnterKind: - Out << "CallEnter\""; + Out << "CallEnter\", \"callee_decl\": \""; + Out << AnalysisDeclContext::getFunctionName( + castAs().getCalleeContext()->getDecl()) + << '\"'; break; case ProgramPoint::CallExitBeginKind: Out << "CallExitBegin\""; diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index acbe1470b389915e5545763c0573a2069455f1bd..dd81c8e0a3d5437e7ed8b852411854794d45c0c0 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -13,11 +13,11 @@ #include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/AST/Attr.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" @@ -476,17 +476,19 @@ static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) { } if (!CoroStmt) return false; - struct Checker : RecursiveASTVisitor { + struct Checker : DynamicRecursiveASTVisitor { const Stmt *DeadStmt; bool CoroutineSubStmt = false; - Checker(const Stmt *S) : DeadStmt(S) {} - bool VisitStmt(const Stmt *S) { + Checker(const Stmt *S) : DeadStmt(S) { + // Statements captured in the CFG can be implicit. + ShouldVisitImplicitCode = true; + } + + bool VisitStmt(Stmt *S) override { if (S == DeadStmt) CoroutineSubStmt = true; return true; } - // Statements captured in the CFG can be implicit. - bool shouldVisitImplicitCode() const { return true; } }; Checker checker(DeadStmt); checker.TraverseStmt(const_cast(CoroStmt)); diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index b683826503c74ce5b58df3f38aff058770e40788..5f36ffa926b2695b9be04e870aaccd7f346c566c 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -9,9 +9,9 @@ #include "clang/Analysis/Analyses/UnsafeBufferUsage.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/FormatString.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" @@ -82,11 +82,8 @@ static std::string getDREAncestorString(const DeclRefExpr *DRE, namespace clang::ast_matchers { // A `RecursiveASTVisitor` that traverses all descendants of a given node "n" // except for those belonging to a different callable of "n". -class MatchDescendantVisitor - : public RecursiveASTVisitor { +class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { public: - typedef RecursiveASTVisitor VisitorBase; - // Creates an AST visitor that matches `Matcher` on all // descendants of a given node "n" except for the ones // belonging to a different callable of "n". @@ -96,7 +93,10 @@ public: internal::ASTMatchFinder::BindKind Bind, const bool ignoreUnevaluatedContext) : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind), - Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) {} + Matches(false), ignoreUnevaluatedContext(ignoreUnevaluatedContext) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; // TODO: let's ignore implicit code for now + } // Returns true if a match is found in a subtree of `DynNode`, which belongs // to the same callable of `DynNode`. @@ -117,7 +117,7 @@ public: // For the matchers so far used in safe buffers, we only need to match // `Stmt`s. To override more as needed. - bool TraverseDecl(Decl *Node) { + bool TraverseDecl(Decl *Node) override { if (!Node) return true; if (!match(*Node)) @@ -126,69 +126,58 @@ public: if (isa(Node)) return true; // Traverse descendants - return VisitorBase::TraverseDecl(Node); + return DynamicRecursiveASTVisitor::TraverseDecl(Node); } - bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) { + bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override { // These are unevaluated, except the result expression. if (ignoreUnevaluatedContext) return TraverseStmt(Node->getResultExpr()); - return VisitorBase::TraverseGenericSelectionExpr(Node); + return DynamicRecursiveASTVisitor::TraverseGenericSelectionExpr(Node); } - bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { + bool + TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseUnaryExprOrTypeTraitExpr(Node); + return DynamicRecursiveASTVisitor::TraverseUnaryExprOrTypeTraitExpr(Node); } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) { + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseTypeOfExprTypeLoc(Node); + return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(Node); } - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) { + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseDecltypeTypeLoc(Node); + return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(Node); } - bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) { + bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseCXXNoexceptExpr(Node); + return DynamicRecursiveASTVisitor::TraverseCXXNoexceptExpr(Node); } - bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) { + bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return VisitorBase::TraverseCXXTypeidExpr(Node); - } - - bool TraverseCXXDefaultInitExpr(CXXDefaultInitExpr *Node) { - if (!TraverseStmt(Node->getExpr())) - return false; - return VisitorBase::TraverseCXXDefaultInitExpr(Node); + return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(Node); } - bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) { + bool TraverseStmt(Stmt *Node) override { if (!Node) return true; if (!match(*Node)) return false; - return VisitorBase::TraverseStmt(Node); - } - - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { - // TODO: let's ignore implicit code for now - return false; + return DynamicRecursiveASTVisitor::TraverseStmt(Node); } private: @@ -366,6 +355,7 @@ isInUnspecifiedUntypedContext(internal::Matcher InnerMatcher) { // 4. `std::span{a, n}`, where `a` is of an array-of-T with constant size // `n` // 5. `std::span{any, 0}` +// 6. `std::span{std::addressof(...), 1}` AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) { assert(Node.getNumArgs() == 2 && "expecting a two-parameter std::span constructor"); @@ -410,6 +400,15 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) { // Check form 3: return Arg1CV && Arg1CV->isOne(); break; + case Stmt::CallExprClass: + if (const auto *CE = dyn_cast(Arg0)) { + const auto FnDecl = CE->getDirectCallee(); + if (FnDecl && FnDecl->getNameAsString() == "addressof" && + FnDecl->isInStdNamespace()) { + return Arg1CV && Arg1CV->isOne(); + } + } + break; default: break; } @@ -1988,18 +1987,14 @@ public: }; /// Scan the function and return a list of gadgets found with provided kits. -static void findGadgets(const Stmt *S, ASTContext &Ctx, - const UnsafeBufferUsageHandler &Handler, - bool EmitSuggestions, FixableGadgetList &FixableGadgets, - WarningGadgetList &WarningGadgets, - DeclUseTracker &Tracker) { +static std::tuple +findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler, + bool EmitSuggestions) { struct GadgetFinderCallback : MatchFinder::MatchCallback { - GadgetFinderCallback(FixableGadgetList &FixableGadgets, - WarningGadgetList &WarningGadgets, - DeclUseTracker &Tracker) - : FixableGadgets(FixableGadgets), WarningGadgets(WarningGadgets), - Tracker(Tracker) {} + FixableGadgetList FixableGadgets; + WarningGadgetList WarningGadgets; + DeclUseTracker Tracker; void run(const MatchFinder::MatchResult &Result) override { // In debug mode, assert that we've found exactly one gadget. @@ -2040,14 +2035,10 @@ static void findGadgets(const Stmt *S, ASTContext &Ctx, assert(numFound >= 1 && "Gadgets not found in match result!"); assert(numFound <= 1 && "Conflicting bind tags in gadgets!"); } - - FixableGadgetList &FixableGadgets; - WarningGadgetList &WarningGadgets; - DeclUseTracker &Tracker; }; MatchFinder M; - GadgetFinderCallback CB{FixableGadgets, WarningGadgets, Tracker}; + GadgetFinderCallback CB; // clang-format off M.addMatcher( @@ -2092,7 +2083,9 @@ static void findGadgets(const Stmt *S, ASTContext &Ctx, // clang-format on } - M.match(*S, Ctx); + M.match(*D->getBody(), D->getASTContext()); + return {std::move(CB.FixableGadgets), std::move(CB.WarningGadgets), + std::move(CB.Tracker)}; } // Compares AST nodes by source locations. @@ -3636,9 +3629,39 @@ public: } }; -void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets, - WarningGadgetList WarningGadgets, DeclUseTracker Tracker, - UnsafeBufferUsageHandler &Handler, bool EmitSuggestions) { +void clang::checkUnsafeBufferUsage(const Decl *D, + UnsafeBufferUsageHandler &Handler, + bool EmitSuggestions) { +#ifndef NDEBUG + Handler.clearDebugNotes(); +#endif + + assert(D && D->getBody()); + // We do not want to visit a Lambda expression defined inside a method + // independently. Instead, it should be visited along with the outer method. + // FIXME: do we want to do the same thing for `BlockDecl`s? + if (const auto *fd = dyn_cast(D)) { + if (fd->getParent()->isLambda() && fd->getParent()->isLocalClass()) + return; + } + + // Do not emit fixit suggestions for functions declared in an + // extern "C" block. + if (const auto *FD = dyn_cast(D)) { + for (FunctionDecl *FReDecl : FD->redecls()) { + if (FReDecl->isExternC()) { + EmitSuggestions = false; + break; + } + } + } + + WarningGadgetSets UnsafeOps; + FixableGadgetSets FixablesForAllVars; + + auto [FixableGadgets, WarningGadgets, Tracker] = + findGadgets(D, Handler, EmitSuggestions); + if (!EmitSuggestions) { // Our job is very easy without suggestions. Just warn about // every problematic operation and consider it done. No need to deal @@ -3682,10 +3705,8 @@ void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets, if (WarningGadgets.empty()) return; - WarningGadgetSets UnsafeOps = - groupWarningGadgetsByVar(std::move(WarningGadgets)); - FixableGadgetSets FixablesForAllVars = - groupFixablesByVar(std::move(FixableGadgets)); + UnsafeOps = groupWarningGadgetsByVar(std::move(WarningGadgets)); + FixablesForAllVars = groupFixablesByVar(std::move(FixableGadgets)); std::map FixItsForVariableGroup; @@ -3906,56 +3927,3 @@ void applyGadgets(const Decl *D, FixableGadgetList FixableGadgets, } } } - -void clang::checkUnsafeBufferUsage(const Decl *D, - UnsafeBufferUsageHandler &Handler, - bool EmitSuggestions) { -#ifndef NDEBUG - Handler.clearDebugNotes(); -#endif - - assert(D); - - SmallVector Stmts; - - if (const auto *FD = dyn_cast(D)) { - // We do not want to visit a Lambda expression defined inside a method - // independently. Instead, it should be visited along with the outer method. - // FIXME: do we want to do the same thing for `BlockDecl`s? - if (const auto *MD = dyn_cast(D)) { - if (MD->getParent()->isLambda() && MD->getParent()->isLocalClass()) - return; - } - - for (FunctionDecl *FReDecl : FD->redecls()) { - if (FReDecl->isExternC()) { - // Do not emit fixit suggestions for functions declared in an - // extern "C" block. - EmitSuggestions = false; - break; - } - } - - Stmts.push_back(FD->getBody()); - - if (const auto *ID = dyn_cast(D)) { - for (const CXXCtorInitializer *CI : ID->inits()) { - Stmts.push_back(CI->getInit()); - } - } - } else if (isa(D) || isa(D)) { - Stmts.push_back(D->getBody()); - } - - assert(!Stmts.empty()); - - FixableGadgetList FixableGadgets; - WarningGadgetList WarningGadgets; - DeclUseTracker Tracker; - for (Stmt *S : Stmts) { - findGadgets(S, D->getASTContext(), Handler, EmitSuggestions, FixableGadgets, - WarningGadgets, Tracker); - } - applyGadgets(D, std::move(FixableGadgets), std::move(WarningGadgets), - std::move(Tracker), Handler, EmitSuggestions); -} diff --git a/clang/lib/Basic/Cuda.cpp b/clang/lib/Basic/Cuda.cpp index d765baef913e2f26615d01de8a7d4ac5b09e9bb5..d56609a2a8f24aaddf881a6b2e5f249a60284ba0 100644 --- a/clang/lib/Basic/Cuda.cpp +++ b/clang/lib/Basic/Cuda.cpp @@ -121,9 +121,11 @@ static const OffloadArchToStringMap arch_names[] = { GFX(909), // gfx909 GFX(90a), // gfx90a GFX(90c), // gfx90c + {OffloadArch::GFX9_4_GENERIC, "gfx9-4-generic", "compute_amdgcn"}, GFX(940), // gfx940 GFX(941), // gfx941 GFX(942), // gfx942 + GFX(950), // gfx950 {OffloadArch::GFX10_1_GENERIC, "gfx10-1-generic", "compute_amdgcn"}, GFX(1010), // gfx1010 GFX(1011), // gfx1011 diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 1034ac0c0036c5eec24159e4a919db9f47a8f1aa..2d0e358116362c0b2beb6edc4b123d597d9aa17e 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -500,14 +500,14 @@ public: // the last section take precedence in such cases. void processSections(DiagnosticsEngine &Diags); - bool isDiagSuppressed(diag::kind DiagId, llvm::StringRef FilePath) const; + bool isDiagSuppressed(diag::kind DiagId, StringRef FilePath) const; private: // Find the longest glob pattern that matches FilePath amongst // CategoriesToMatchers, return true iff the match exists and belongs to a // positive category. bool globsMatches(const llvm::StringMap &CategoriesToMatchers, - llvm::StringRef FilePath) const; + StringRef FilePath) const; llvm::DenseMap DiagToSection; }; @@ -532,7 +532,7 @@ void WarningsSpecialCaseList::processSections(DiagnosticsEngine &Diags) { LineAndSectionEntry; LineAndSectionEntry.reserve(Sections.size()); for (const auto &Entry : Sections) { - llvm::StringRef DiagName = Entry.getKey(); + StringRef DiagName = Entry.getKey(); // Each section has a matcher with that section's name, attached to that // line. const auto &DiagSectionMatcher = Entry.getValue().SectionMatcher; @@ -543,7 +543,7 @@ void WarningsSpecialCaseList::processSections(DiagnosticsEngine &Diags) { static constexpr auto WarningFlavor = clang::diag::Flavor::WarningOrError; for (const auto &[_, SectionEntry] : LineAndSectionEntry) { SmallVector GroupDiags; - llvm::StringRef DiagGroup = SectionEntry->getKey(); + StringRef DiagGroup = SectionEntry->getKey(); if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup( WarningFlavor, DiagGroup, GroupDiags)) { StringRef Suggestion = @@ -564,6 +564,8 @@ void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) { std::string Error; auto WarningSuppressionList = WarningsSpecialCaseList::create(Input, Error); if (!WarningSuppressionList) { + // FIXME: Use a `%select` statement instead of printing `Error` as-is. This + // should help localization. Report(diag::err_drv_malformed_warning_suppression_mapping) << Input.getBufferIdentifier() << Error; return; @@ -571,13 +573,13 @@ void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) { WarningSuppressionList->processSections(*this); DiagSuppressionMapping = [WarningSuppressionList(std::move(WarningSuppressionList))]( - diag::kind DiagId, llvm::StringRef Path) { + diag::kind DiagId, StringRef Path) { return WarningSuppressionList->isDiagSuppressed(DiagId, Path); }; } bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId, - llvm::StringRef FilePath) const { + StringRef FilePath) const { const Section *DiagSection = DiagToSection.lookup(DiagId); if (!DiagSection) return false; @@ -592,11 +594,11 @@ bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId, bool WarningsSpecialCaseList::globsMatches( const llvm::StringMap &CategoriesToMatchers, - llvm::StringRef FilePath) const { - llvm::StringRef LongestMatch; + StringRef FilePath) const { + StringRef LongestMatch; bool LongestIsPositive = false; for (const auto &Entry : CategoriesToMatchers) { - llvm::StringRef Category = Entry.getKey(); + StringRef Category = Entry.getKey(); const llvm::SpecialCaseList::Matcher &Matcher = Entry.getValue(); bool IsPositive = Category != "emit"; for (const auto &[Pattern, Glob] : Matcher.Globs) { @@ -612,7 +614,7 @@ bool WarningsSpecialCaseList::globsMatches( } bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId, - llvm::StringRef FilePath) const { + StringRef FilePath) const { return DiagSuppressionMapping && DiagSuppressionMapping(DiagId, FilePath); } @@ -791,6 +793,35 @@ static void HandleOrdinalModifier(unsigned ValNo, Out << ValNo << llvm::getOrdinalSuffix(ValNo); } +// 123 -> "123". +// 1234 -> "1.23k". +// 123456 -> "123.46k". +// 1234567 -> "1.23M". +// 1234567890 -> "1.23G". +// 1234567890123 -> "1.23T". +static void HandleIntegerHumanModifier(int64_t ValNo, + SmallVectorImpl &OutStr) { + static constexpr std::array, 4> Units = { + {{1'000'000'000'000L, 'T'}, + {1'000'000'000L, 'G'}, + {1'000'000L, 'M'}, + {1'000L, 'k'}}}; + + llvm::raw_svector_ostream Out(OutStr); + if (ValNo < 0) { + Out << "-"; + ValNo = -ValNo; + } + for (const auto &[UnitSize, UnitSign] : Units) { + if (ValNo >= UnitSize) { + Out << llvm::format("%0.2f%c", ValNo / static_cast(UnitSize), + UnitSign); + return; + } + } + Out << ValNo; +} + /// PluralNumber - Parse an unsigned integer and advance Start. static unsigned PluralNumber(const char *&Start, const char *End) { // Programming 101: Parse a decimal number :-) @@ -1127,6 +1158,8 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, OutStr); } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { HandleOrdinalModifier((unsigned)Val, OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "human")) { + HandleIntegerHumanModifier(Val, OutStr); } else { assert(ModifierLen == 0 && "Unknown integer modifier"); llvm::raw_svector_ostream(OutStr) << Val; @@ -1145,6 +1178,8 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd, OutStr); } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) { HandleOrdinalModifier(Val, OutStr); + } else if (ModifierIs(Modifier, ModifierLen, "human")) { + HandleIntegerHumanModifier(Val, OutStr); } else { assert(ModifierLen == 0 && "Unknown integer modifier"); llvm::raw_svector_ostream(OutStr) << Val; diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index ccce70d18ebf544482375dda6587c81fed81c233..44922aa7872dbf76b52299d376db4e967fdc231a 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -601,7 +601,7 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, return diag::Severity::Ignored; // Clang-diagnostics pragmas always take precedence over suppression mapping. - if (!Mapping.isPragma()) { + if (!Mapping.isPragma() && Diag.DiagSuppressionMapping) { // We also use presumed locations here to improve reproducibility for // preprocessed inputs. if (PresumedLoc PLoc = SM.getPresumedLoc(Loc); diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index af60348ef2655555cec92470626a2274cc99370e..6e588ce63d813f739a0d852a7cee05da4fa326d7 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -29,7 +29,6 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -666,7 +665,7 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); if (NextLocalOffset + Length + 1 <= NextLocalOffset || NextLocalOffset + Length + 1 > CurrentLoadedOffset) { - Diag.Report(SourceLocation(), diag::err_sloc_space_too_large); + Diag.Report(diag::err_sloc_space_too_large); // FIXME: call `noteSLocAddressSpaceUsage` to report details to users and // use a source location from `Info` to point at an error. // Currently, both cause Clang to run indefinitely, this needs to be fixed. @@ -2228,28 +2227,6 @@ LLVM_DUMP_METHOD void SourceManager::dump() const { } } -// 123 -> "123". -// 1234 -> "1.23k". -// 123456 -> "123.46k". -// 1234567 -> "1.23M". -// 1234567890 -> "1.23G". -// 1234567890123 -> "1.23T". -static std::string humanizeNumber(uint64_t Number) { - static constexpr std::array, 4> Units = { - {{1'000'000'000'000UL, 'T'}, - {1'000'000'000UL, 'G'}, - {1'000'000UL, 'M'}, - {1'000UL, 'k'}}}; - - for (const auto &[UnitSize, UnitSign] : Units) { - if (Number >= UnitSize) { - return llvm::formatv("{0:F}{1}", Number / static_cast(UnitSize), - UnitSign); - } - } - return std::to_string(Number); -} - void SourceManager::noteSLocAddressSpaceUsage( DiagnosticsEngine &Diag, std::optional MaxNotes) const { struct Info { @@ -2318,10 +2295,9 @@ void SourceManager::noteSLocAddressSpaceUsage( uint64_t LoadedUsage = MaxLoadedOffset - CurrentLoadedOffset; int UsagePercent = static_cast(100.0 * double(LocalUsage + LoadedUsage) / MaxLoadedOffset); - Diag.Report(SourceLocation(), diag::note_total_sloc_usage) - << LocalUsage << humanizeNumber(LocalUsage) << LoadedUsage - << humanizeNumber(LoadedUsage) << (LocalUsage + LoadedUsage) - << humanizeNumber(LocalUsage + LoadedUsage) << UsagePercent; + Diag.Report(diag::note_total_sloc_usage) + << LocalUsage << LoadedUsage << (LocalUsage + LoadedUsage) + << UsagePercent; // Produce notes on sloc address space usage for each file with a high usage. uint64_t ReportedSize = 0; @@ -2329,17 +2305,14 @@ void SourceManager::noteSLocAddressSpaceUsage( llvm::make_range(SortedUsage.begin(), SortedEnd)) { Diag.Report(FileInfo.Loc, diag::note_file_sloc_usage) << FileInfo.Inclusions << FileInfo.DirectSize - << humanizeNumber(FileInfo.DirectSize) - << (FileInfo.TotalSize - FileInfo.DirectSize) - << humanizeNumber(FileInfo.TotalSize - FileInfo.DirectSize); + << (FileInfo.TotalSize - FileInfo.DirectSize); ReportedSize += FileInfo.TotalSize; } // Describe any remaining usage not reported in the per-file usage. if (ReportedSize != CountedSize) { - Diag.Report(SourceLocation(), diag::note_file_misc_sloc_usage) - << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize - << humanizeNumber(CountedSize - ReportedSize); + Diag.Report(diag::note_file_misc_sloc_usage) + << (SortedUsage.end() - SortedEnd) << CountedSize - ReportedSize; } } diff --git a/clang/lib/Basic/TargetDefines.h b/clang/lib/Basic/TargetDefines.h new file mode 100644 index 0000000000000000000000000000000000000000..96fc4fe70fa9d285c1eba7835f5585d613894de1 --- /dev/null +++ b/clang/lib/Basic/TargetDefines.h @@ -0,0 +1,39 @@ +//===------- TargetDefines.h - Target define helpers ------------*- 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 declares a series of helper functions for defining target-specific +// macros. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_BASIC_TARGETDEFINES_H +#define LLVM_CLANG_LIB_BASIC_TARGETDEFINES_H + +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/MacroBuilder.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { +namespace targets { +/// Define a macro name and standard variants. For example if MacroName is +/// "unix", then this will define "__unix", "__unix__", and "unix" when in GNU +/// mode. +LLVM_LIBRARY_VISIBILITY +void DefineStd(clang::MacroBuilder &Builder, llvm::StringRef MacroName, + const clang::LangOptions &Opts); + +LLVM_LIBRARY_VISIBILITY +void defineCPUMacros(clang::MacroBuilder &Builder, llvm::StringRef CPUName, + bool Tuning = true); + +LLVM_LIBRARY_VISIBILITY +void addCygMingDefines(const clang::LangOptions &Opts, + clang::MacroBuilder &Builder); +} // namespace targets +} // namespace clang +#endif // LLVM_CLANG_LIB_BASIC_TARGETDEFINES_H diff --git a/clang/lib/Basic/Targets.h b/clang/lib/Basic/Targets.h index b4d2486b5d2b13c5a3e56d8fb4d1ec4ef406a0b0..e1458384fa1c8b938a296e4af8e2a3cfbc4e3155 100644 --- a/clang/lib/Basic/Targets.h +++ b/clang/lib/Basic/Targets.h @@ -15,32 +15,7 @@ #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_H #define LLVM_CLANG_LIB_BASIC_TARGETS_H -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/MacroBuilder.h" +#include "TargetDefines.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/StringRef.h" -namespace clang { -namespace targets { - -LLVM_LIBRARY_VISIBILITY -std::unique_ptr -AllocateTarget(const llvm::Triple &Triple, const clang::TargetOptions &Opts); - -/// DefineStd - Define a macro name and standard variants. For example if -/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix" -/// when in GNU mode. -LLVM_LIBRARY_VISIBILITY -void DefineStd(clang::MacroBuilder &Builder, llvm::StringRef MacroName, - const clang::LangOptions &Opts); - -LLVM_LIBRARY_VISIBILITY -void defineCPUMacros(clang::MacroBuilder &Builder, llvm::StringRef CPUName, - bool Tuning = true); - -LLVM_LIBRARY_VISIBILITY -void addCygMingDefines(const clang::LangOptions &Opts, - clang::MacroBuilder &Builder); -} // namespace targets -} // namespace clang #endif // LLVM_CLANG_LIB_BASIC_TARGETS_H diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index e35ee2b7b9c385396d3676eb960d76962ee5cc81..eb8a3ada0344827110c77332507efe8bf88b541b 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -473,7 +473,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasSVE2p1) Builder.defineMacro("__ARM_FEATURE_SVE2p1", "1"); - if (HasSVE2 && HasSVE2AES) + if (HasSVE2 && HasSVEAES) Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1"); if (HasSVE2 && HasSVE2BitPerm) @@ -722,7 +722,7 @@ unsigned AArch64TargetInfo::multiVersionFeatureCost() const { bool AArch64TargetInfo::doesFeatureAffectCodeGen(StringRef Name) const { // FMV extensions which imply no backend features do not affect codegen. if (auto Ext = llvm::AArch64::parseFMVExtension(Name)) - return !Ext->Features.empty(); + return Ext->ID.has_value(); return false; } @@ -769,7 +769,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { .Case("f32mm", FPU & SveMode && HasMatmulFP32) .Case("f64mm", FPU & SveMode && HasMatmulFP64) .Case("sve2", FPU & SveMode && HasSVE2) - .Case("sve2-pmull128", FPU & SveMode && HasSVE2AES) + .Case("sve-aes", HasSVEAES) .Case("sve2-bitperm", FPU & SveMode && HasSVE2BitPerm) .Case("sve2-sha3", FPU & SveMode && HasSVE2SHA3) .Case("sve2-sm4", FPU & SveMode && HasSVE2SM4) @@ -861,12 +861,10 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features, HasSVE2 = true; HasSVE2p1 = true; } - if (Feature == "+sve2-aes") { + if (Feature == "+sve-aes") { FPU |= NeonMode; - FPU |= SveMode; HasFullFP16 = true; - HasSVE2 = true; - HasSVE2AES = true; + HasSVEAES = true; } if (Feature == "+sve2-sha3") { FPU |= NeonMode; diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index ea3e4015d842653eca5b353186e181343d141ce7..4c25bdb5bb16df0018d5c5f5404478f24166e1e6 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -78,7 +78,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { bool HasBFloat16 = false; bool HasSVE2 = false; bool HasSVE2p1 = false; - bool HasSVE2AES = false; + bool HasSVEAES = false; bool HasSVE2SHA3 = false; bool HasSVE2SM4 = false; bool HasSVEB16B16 = false; diff --git a/clang/lib/Basic/Targets/AMDGPU.h b/clang/lib/Basic/Targets/AMDGPU.h index fac46f215a3736a815d651980627494772827678..db7a095ba2a4fe07d2bdbf1798018e77f7531fe3 100644 --- a/clang/lib/Basic/Targets/AMDGPU.h +++ b/clang/lib/Basic/Targets/AMDGPU.h @@ -111,6 +111,18 @@ public: return getPointerWidthV(AddrSpace); } + virtual bool isAddressSpaceSupersetOf(LangAS A, LangAS B) const override { + // The flat address space AS(0) is a superset of all the other address + // spaces used by the backend target. + return A == B || + ((A == LangAS::Default || + (isTargetAddressSpace(A) && + toTargetAddressSpace(A) == llvm::AMDGPUAS::FLAT_ADDRESS)) && + isTargetAddressSpace(B) && + toTargetAddressSpace(B) >= llvm::AMDGPUAS::FLAT_ADDRESS && + toTargetAddressSpace(B) <= llvm::AMDGPUAS::PRIVATE_ADDRESS); + } + uint64_t getMaxPointerWidth() const override { return getTriple().getArch() == llvm::Triple::amdgcn ? 64 : 32; } diff --git a/clang/lib/Basic/Targets/NVPTX.cpp b/clang/lib/Basic/Targets/NVPTX.cpp index e0bd0b096324d8dfbd0c180e574d42902c4ea543..dbc3fec36576107ac42e5a38f043365061191d8b 100644 --- a/clang/lib/Basic/Targets/NVPTX.cpp +++ b/clang/lib/Basic/Targets/NVPTX.cpp @@ -205,9 +205,11 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts, case OffloadArch::GFX909: case OffloadArch::GFX90a: case OffloadArch::GFX90c: + case OffloadArch::GFX9_4_GENERIC: case OffloadArch::GFX940: case OffloadArch::GFX941: case OffloadArch::GFX942: + case OffloadArch::GFX950: case OffloadArch::GFX10_1_GENERIC: case OffloadArch::GFX1010: case OffloadArch::GFX1011: diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h index 165b28a60fb2a92e27ffef00dcc29b4f71e995be..d81b89a7f24ac030297089a68233154bacf6b56a 100644 --- a/clang/lib/Basic/Targets/NVPTX.h +++ b/clang/lib/Basic/Targets/NVPTX.h @@ -17,6 +17,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/NVPTXAddrSpace.h" #include "llvm/TargetParser/Triple.h" #include @@ -89,6 +90,20 @@ public: bool hasFeature(StringRef Feature) const override; + virtual bool isAddressSpaceSupersetOf(LangAS A, LangAS B) const override { + // The generic address space AS(0) is a superset of all the other address + // spaces used by the backend target. + return A == B || + ((A == LangAS::Default || + (isTargetAddressSpace(A) && + toTargetAddressSpace(A) == + llvm::NVPTXAS::ADDRESS_SPACE_GENERIC)) && + isTargetAddressSpace(B) && + toTargetAddressSpace(B) >= llvm::NVPTXAS::ADDRESS_SPACE_GENERIC && + toTargetAddressSpace(B) <= llvm::NVPTXAS::ADDRESS_SPACE_LOCAL && + toTargetAddressSpace(B) != 2); + } + ArrayRef getGCCRegNames() const override; ArrayRef getGCCRegAliases() const override { diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 50d35922fe683adb37ae20f58548bc76d9e35e22..ce70f01f3387754611317638f5b8a73d00c69db3 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -108,6 +108,10 @@ bool RISCVTargetInfo::validateAsmConstraint( return true; } return false; + case 'R': + // An even-odd GPR pair + Info.setAllowsRegister(); + return true; case 'v': // A vector register. if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') { diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 086b4415412e6734222e14296b65f9d674d4bea0..5993257e27d5a94d4d2b7e7844e431f2bcbf82e5 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -667,6 +667,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, case CK_GraniterapidsD: case CK_Emeraldrapids: case CK_Clearwaterforest: + case CK_Diamondrapids: // FIXME: Historically, we defined this legacy name, it would be nice to // remove it at some point. We've never exposed fine-grained names for // recent primary x86 CPUs, and we should keep it that way. @@ -1651,6 +1652,7 @@ std::optional X86TargetInfo::getCPUCacheLineSize() const { case CK_GraniterapidsD: case CK_Emeraldrapids: case CK_Clearwaterforest: + case CK_Diamondrapids: case CK_KNL: case CK_KNM: // K7 diff --git a/clang/lib/Basic/Warnings.cpp b/clang/lib/Basic/Warnings.cpp index 7145a65fe5d26df00dbf5dab80036f3b39647e22..da0304463007b65df72e7572bb145972e671ab0b 100644 --- a/clang/lib/Basic/Warnings.cpp +++ b/clang/lib/Basic/Warnings.cpp @@ -27,11 +27,8 @@ #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/VirtualFileSystem.h" #include -#include -#include using namespace clang; // EmitUnknownDiagWarning - Emit a warning and typo hint for unknown warning diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 4e8a8cc3f4c524fa3baf3fc22078297cf0a4f872..5963d43bb9672f8fab205214efa56fbd88b78f54 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -50,7 +50,7 @@ mlir::Location CIRGenModule::getLoc(SourceRange cRange) { return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext()); } -void CIRGenModule::buildGlobal(clang::GlobalDecl gd) { +void CIRGenModule::emitGlobal(clang::GlobalDecl gd) { const auto *global = cast(gd.getDecl()); if (const auto *fd = dyn_cast(global)) { @@ -71,19 +71,19 @@ void CIRGenModule::buildGlobal(clang::GlobalDecl gd) { } // TODO(CIR): Defer emitting some global definitions until later - buildGlobalDefinition(gd); + emitGlobalDefinition(gd); } -void CIRGenModule::buildGlobalFunctionDefinition(clang::GlobalDecl gd, - mlir::Operation *op) { +void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd, + mlir::Operation *op) { auto const *funcDecl = cast(gd.getDecl()); auto funcOp = builder.create( getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName()); theModule.push_back(funcOp); } -void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd, - mlir::Operation *op) { +void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd, + mlir::Operation *op) { const auto *decl = cast(gd.getDecl()); if (const auto *fd = dyn_cast(decl)) { // TODO(CIR): Skip generation of CIR for functions with available_externally @@ -99,15 +99,15 @@ void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd, if (fd->isMultiVersion()) errorNYI(fd->getSourceRange(), "multiversion functions"); - buildGlobalFunctionDefinition(gd, op); + emitGlobalFunctionDefinition(gd, op); return; } - llvm_unreachable("Invalid argument to CIRGenModule::buildGlobalDefinition"); + llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition"); } // Emit code for a single top level declaration. -void CIRGenModule::buildTopLevelDecl(Decl *decl) { +void CIRGenModule::emitTopLevelDecl(Decl *decl) { // Ignore dependent declarations. if (decl->isTemplated()) @@ -123,7 +123,7 @@ void CIRGenModule::buildTopLevelDecl(Decl *decl) { auto *fd = cast(decl); // Consteval functions shouldn't be emitted. if (!fd->isConsteval()) - buildGlobal(fd); + emitGlobal(fd); break; } } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 9e5950ff71c528c95bba1ab4225b1acaedb08328..aaded92e6a633e8deb4a9eb72df9fb9334824e6a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -72,15 +72,15 @@ public: mlir::Location getLoc(clang::SourceLocation cLoc); mlir::Location getLoc(clang::SourceRange cRange); - void buildTopLevelDecl(clang::Decl *decl); + void emitTopLevelDecl(clang::Decl *decl); /// Emit code for a single global function or variable declaration. Forward /// declarations are emitted lazily. - void buildGlobal(clang::GlobalDecl gd); + void emitGlobal(clang::GlobalDecl gd); - void buildGlobalDefinition(clang::GlobalDecl gd, - mlir::Operation *op = nullptr); - void buildGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op); + void emitGlobalDefinition(clang::GlobalDecl gd, + mlir::Operation *op = nullptr); + void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op); /// Helpers to emit "not yet implemented" error diagnostics DiagnosticBuilder errorNYI(llvm::StringRef); diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp index 85367a916ef7830fedb24e7579926ba405c42872..8f3370c0041afef48909636be6a33b58cc64e5fc 100644 --- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp @@ -45,7 +45,7 @@ mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); } bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) { for (Decl *decl : group) - cgm->buildTopLevelDecl(decl); + cgm->emitTopLevelDecl(decl); return true; } diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt index 1518e8c760609cbe02cde94a98586096d4a87770..75cee3f8711307206d53b0948228a4b82758a676 100644 --- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt @@ -3,6 +3,9 @@ add_clang_library(MLIRCIR CIRDialect.cpp CIRTypes.cpp + DEPENDS + MLIRCIROpsIncGen + LINK_LIBS PUBLIC MLIRIR ) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 4534fd9ae0ae56fb997c8afde5b1847c26dbfbb2..a36e3b8b968f2d417bd2b508475d2f1558ed838b 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -16,18 +16,14 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeWriterPass.h" -#include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/Frontend/Driver/CodeGenOptions.h" #include "llvm/IR/DataLayout.h" @@ -39,7 +35,6 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRPrinter/IRPrintingPasses.h" #include "llvm/LTO/LTOBackend.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/OffloadBinary.h" #include "llvm/Passes/PassBuilder.h" diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index f8736695acf18772303ea3e218f06ee859e376fe..f6cb2ad421e90609cc0d198a8ac971ddf58f6704 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -21,7 +21,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Operator.h" using namespace clang; using namespace CodeGen; diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index bfa9b0a2f836bc8331adba14333d1cf1f334bfec..a7584a95c8ca7b90f40ec6312a92e5df651bb581 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -22,7 +22,6 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/CodeGen/ConstantInitBuilder.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Module.h" #include "llvm/Support/ScopedPrinter.h" @@ -2837,10 +2836,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() { if (BlockObjectDispose) return BlockObjectDispose; - llvm::Type *args[] = { Int8PtrTy, Int32Ty }; - llvm::FunctionType *fty - = llvm::FunctionType::get(VoidTy, args, false); - BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); + QualType args[] = {Context.VoidPtrTy, Context.IntTy}; + BlockObjectDispose = + CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_dispose"); configureBlocksRuntimeObject( *this, cast(BlockObjectDispose.getCallee())); return BlockObjectDispose; @@ -2850,10 +2848,9 @@ llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() { if (BlockObjectAssign) return BlockObjectAssign; - llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; - llvm::FunctionType *fty - = llvm::FunctionType::get(VoidTy, args, false); - BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); + QualType args[] = {Context.VoidPtrTy, Context.VoidPtrTy, Context.IntTy}; + BlockObjectAssign = + CreateRuntimeFunction(Context.VoidTy, args, "_Block_object_assign"); configureBlocksRuntimeObject( *this, cast(BlockObjectAssign.getCallee())); return BlockObjectAssign; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1acc7e82f3390567b81d39e146a5cc655cc51bad..7e3ec93c1d44955d2a6bc914a1adcd9b279343cc 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -56,7 +56,6 @@ #include "llvm/IR/IntrinsicsEPI.h" #include "llvm/IR/IntrinsicsRISCV.h" #include "llvm/IR/IntrinsicsS390.h" -#include "llvm/IR/IntrinsicsVE.h" #include "llvm/IR/IntrinsicsWebAssembly.h" #include "llvm/IR/IntrinsicsX86.h" #include "llvm/IR/MDBuilder.h" @@ -70,7 +69,6 @@ #include "llvm/TargetParser/RISCVISAInfo.h" #include "llvm/TargetParser/X86TargetParser.h" #include -#include #include using namespace clang; @@ -100,6 +98,47 @@ static void initializeAlloca(CodeGenFunction &CGF, AllocaInst *AI, Value *Size, I->addAnnotationMetadata("auto-init"); } +static Value *handleHlslClip(const CallExpr *E, CodeGenFunction *CGF) { + Value *Op0 = CGF->EmitScalarExpr(E->getArg(0)); + + Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy); + Value *CMP; + Value *LastInstr; + + if (const auto *VecTy = E->getArg(0)->getType()->getAs()) { + FZeroConst = ConstantVector::getSplat( + ElementCount::getFixed(VecTy->getNumElements()), FZeroConst); + auto *FCompInst = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); + CMP = CGF->Builder.CreateIntrinsic( + CGF->Builder.getInt1Ty(), CGF->CGM.getHLSLRuntime().getAnyIntrinsic(), + {FCompInst}, nullptr); + } else + CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst); + + if (CGF->CGM.getTarget().getTriple().isDXIL()) + LastInstr = CGF->Builder.CreateIntrinsic( + CGF->VoidTy, llvm::Intrinsic::dx_discard, {CMP}, nullptr); + else if (CGF->CGM.getTarget().getTriple().isSPIRV()) { + BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn); + BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn); + + CGF->Builder.CreateCondBr(CMP, LT0, End); + + CGF->Builder.SetInsertPoint(LT0); + + CGF->Builder.CreateIntrinsic(CGF->VoidTy, llvm::Intrinsic::spv_discard, {}, + nullptr); + + LastInstr = CGF->Builder.CreateBr(End); + + CGF->Builder.SetInsertPoint(End); + } else { + llvm_unreachable("Backend Codegen not supported."); + } + + return LastInstr; +} + static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) { Value *Op0 = CGF->EmitScalarExpr(E->getArg(0)); const auto *OutArg1 = dyn_cast(E->getArg(1)); @@ -2799,6 +2838,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( *this, E, Intrinsic::atan, Intrinsic::experimental_constrained_atan)); + case Builtin::BIatan2: + case Builtin::BIatan2f: + case Builtin::BIatan2l: + case Builtin::BI__builtin_atan2: + case Builtin::BI__builtin_atan2f: + case Builtin::BI__builtin_atan2f16: + case Builtin::BI__builtin_atan2l: + case Builtin::BI__builtin_atan2f128: + return RValue::get(emitBinaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::atan2, + Intrinsic::experimental_constrained_atan2)); + case Builtin::BIceil: case Builtin::BIceilf: case Builtin::BIceill: @@ -5163,6 +5214,136 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.SetInsertPoint(ContBB); return RValue::get(nullptr); } + case Builtin::BI__scoped_atomic_thread_fence: { + auto ScopeModel = AtomicScopeModel::create(AtomicScopeModelKind::Generic); + + Value *Order = EmitScalarExpr(E->getArg(0)); + Value *Scope = EmitScalarExpr(E->getArg(1)); + auto Ord = dyn_cast(Order); + auto Scp = dyn_cast(Scope); + if (Ord && Scp) { + SyncScope SS = ScopeModel->isValid(Scp->getZExtValue()) + ? ScopeModel->map(Scp->getZExtValue()) + : ScopeModel->map(ScopeModel->getFallBackValue()); + switch (Ord->getZExtValue()) { + case 0: // memory_order_relaxed + default: // invalid order + break; + case 1: // memory_order_consume + case 2: // memory_order_acquire + Builder.CreateFence( + llvm::AtomicOrdering::Acquire, + getTargetHooks().getLLVMSyncScopeID(getLangOpts(), SS, + llvm::AtomicOrdering::Acquire, + getLLVMContext())); + break; + case 3: // memory_order_release + Builder.CreateFence( + llvm::AtomicOrdering::Release, + getTargetHooks().getLLVMSyncScopeID(getLangOpts(), SS, + llvm::AtomicOrdering::Release, + getLLVMContext())); + break; + case 4: // memory_order_acq_rel + Builder.CreateFence(llvm::AtomicOrdering::AcquireRelease, + getTargetHooks().getLLVMSyncScopeID( + getLangOpts(), SS, + llvm::AtomicOrdering::AcquireRelease, + getLLVMContext())); + break; + case 5: // memory_order_seq_cst + Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent, + getTargetHooks().getLLVMSyncScopeID( + getLangOpts(), SS, + llvm::AtomicOrdering::SequentiallyConsistent, + getLLVMContext())); + break; + } + return RValue::get(nullptr); + } + + llvm::BasicBlock *ContBB = createBasicBlock("atomic.scope.continue", CurFn); + + llvm::SmallVector> + OrderBBs; + if (Ord) { + switch (Ord->getZExtValue()) { + case 0: // memory_order_relaxed + default: // invalid order + ContBB->eraseFromParent(); + return RValue::get(nullptr); + case 1: // memory_order_consume + case 2: // memory_order_acquire + OrderBBs.emplace_back(Builder.GetInsertBlock(), + llvm::AtomicOrdering::Acquire); + break; + case 3: // memory_order_release + OrderBBs.emplace_back(Builder.GetInsertBlock(), + llvm::AtomicOrdering::Release); + break; + case 4: // memory_order_acq_rel + OrderBBs.emplace_back(Builder.GetInsertBlock(), + llvm::AtomicOrdering::AcquireRelease); + break; + case 5: // memory_order_seq_cst + OrderBBs.emplace_back(Builder.GetInsertBlock(), + llvm::AtomicOrdering::SequentiallyConsistent); + break; + } + } else { + llvm::BasicBlock *AcquireBB = createBasicBlock("acquire", CurFn); + llvm::BasicBlock *ReleaseBB = createBasicBlock("release", CurFn); + llvm::BasicBlock *AcqRelBB = createBasicBlock("acqrel", CurFn); + llvm::BasicBlock *SeqCstBB = createBasicBlock("seqcst", CurFn); + + Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false); + llvm::SwitchInst *SI = Builder.CreateSwitch(Order, ContBB); + SI->addCase(Builder.getInt32(1), AcquireBB); + SI->addCase(Builder.getInt32(2), AcquireBB); + SI->addCase(Builder.getInt32(3), ReleaseBB); + SI->addCase(Builder.getInt32(4), AcqRelBB); + SI->addCase(Builder.getInt32(5), SeqCstBB); + + OrderBBs.emplace_back(AcquireBB, llvm::AtomicOrdering::Acquire); + OrderBBs.emplace_back(ReleaseBB, llvm::AtomicOrdering::Release); + OrderBBs.emplace_back(AcqRelBB, llvm::AtomicOrdering::AcquireRelease); + OrderBBs.emplace_back(SeqCstBB, + llvm::AtomicOrdering::SequentiallyConsistent); + } + + for (auto &[OrderBB, Ordering] : OrderBBs) { + Builder.SetInsertPoint(OrderBB); + if (Scp) { + SyncScope SS = ScopeModel->isValid(Scp->getZExtValue()) + ? ScopeModel->map(Scp->getZExtValue()) + : ScopeModel->map(ScopeModel->getFallBackValue()); + Builder.CreateFence(Ordering, + getTargetHooks().getLLVMSyncScopeID( + getLangOpts(), SS, Ordering, getLLVMContext())); + Builder.CreateBr(ContBB); + } else { + llvm::DenseMap BBs; + for (unsigned Scp : ScopeModel->getRuntimeValues()) + BBs[Scp] = createBasicBlock(getAsString(ScopeModel->map(Scp)), CurFn); + + auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false); + llvm::SwitchInst *SI = Builder.CreateSwitch(SC, ContBB); + for (unsigned Scp : ScopeModel->getRuntimeValues()) { + auto *B = BBs[Scp]; + SI->addCase(Builder.getInt32(Scp), B); + + Builder.SetInsertPoint(B); + Builder.CreateFence(Ordering, getTargetHooks().getLLVMSyncScopeID( + getLangOpts(), ScopeModel->map(Scp), + Ordering, getLLVMContext())); + Builder.CreateBr(ContBB); + } + } + } + + Builder.SetInsertPoint(ContBB); + return RValue::get(nullptr); + } case Builtin::BI__builtin_signbit: case Builtin::BI__builtin_signbitf: @@ -5933,15 +6114,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Block = Builder.CreatePointerCast(Info.BlockArg, GenericVoidPtrTy); - AttrBuilder B(Builder.getContext()); - B.addByValAttr(NDRangeL.getAddress().getElementType()); - llvm::AttributeList ByValAttrSet = - llvm::AttributeList::get(CGM.getModule().getContext(), 3U, B); - - auto RTCall = - EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name, ByValAttrSet), - {Queue, Flags, Range, Kernel, Block}); - RTCall->setAttributes(ByValAttrSet); + auto RTCall = EmitRuntimeCall(CGM.CreateRuntimeFunction(FTy, Name), + {Queue, Flags, Range, Kernel, Block}); return RValue::get(RTCall); } assert(NumArgs >= 5 && "Invalid enqueue_kernel signature"); @@ -19197,6 +19371,10 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: { "asuint operands types mismatch"); return handleHlslSplitdouble(E, this); } + case Builtin::BI__builtin_hlsl_elementwise_clip: + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + "clip operands types mismatch"); + return handleHlslClip(E, this); } return nullptr; } diff --git a/clang/lib/CodeGen/CGCUDARuntime.cpp b/clang/lib/CodeGen/CGCUDARuntime.cpp index 1e1da1e2411a7628f86210720ee525a453ed6e7b..121a481213396a74878bba8d5ae4d857255dd71a 100644 --- a/clang/lib/CodeGen/CGCUDARuntime.cpp +++ b/clang/lib/CodeGen/CGCUDARuntime.cpp @@ -15,7 +15,6 @@ #include "CGCUDARuntime.h" #include "CGCall.h" #include "CodeGenFunction.h" -#include "clang/AST/Decl.h" #include "clang/AST/ExprCXX.h" using namespace clang; diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 23ebbee19bf79160d518e33213cf6e01c6645649..78a7b021855b7e8a68a7981917343a05739d591d 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -22,9 +22,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/StmtCXX.h" #include "clang/Basic/CodeGenOptions.h" -#include "llvm/ADT/StringExtras.h" using namespace clang; using namespace CodeGen; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3bc498d2e91f2d8af2f577c6275073bff7cefcbc..a3facc47a72a76ab827eb713eeae08afdfb56da8 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -40,7 +40,6 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Type.h" -#include "llvm/Support/Path.h" #include "llvm/Transforms/Utils/Local.h" #include using namespace clang; diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 352955749a6332576bde507bdcad20118f1fae97..c45688bd1ed3ce88ca4c248def3fc5b0b425e9a6 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -25,7 +25,6 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtCXX.h" #include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/TargetBuiltins.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Metadata.h" diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index ad64abe7cd40a39a2e3851c966444fbde89698f5..60f32f76109e9a5d116b7a963f0358c5a7d3b2c7 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -30,7 +30,6 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/VTableBuilder.h" #include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Version.h" #include "clang/CodeGen/ModuleBuilder.h" @@ -48,7 +47,6 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" #include "llvm/Support/SHA1.h" diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 1d0660292cecc1e40279ffe01377048afc27b19c..47b21bc9f63f0452ed6616e50b6415298b3bb3aa 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -29,7 +29,6 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclOpenMP.h" #include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Sema/Sema.h" @@ -1900,13 +1899,16 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { const Address Loc = locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; + auto hasNoTrivialAutoVarInitAttr = [&](const Decl *D) { + return D && D->hasAttr(); + }; // Note: constexpr already initializes everything correctly. LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = - (D.isConstexpr() + ((D.isConstexpr() || D.getAttr() || + hasNoTrivialAutoVarInitAttr(type->getAsTagDecl()) || + hasNoTrivialAutoVarInitAttr(CurFuncDecl)) ? LangOptions::TrivialAutoVarInitKind::Uninitialized - : (D.getAttr() - ? LangOptions::TrivialAutoVarInitKind::Uninitialized - : getContext().getLangOpts().getTrivialAutoVarInit())); + : getContext().getLangOpts().getTrivialAutoVarInit()); auto initializeWhatIsTechnicallyUninitialized = [&](Address Loc) { if (trivialAutoVarInit == @@ -1945,13 +1947,13 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { replaceUndef(CGM, isPattern, constant)); } - if (constant && D.getType()->isBitIntType() && - CGM.getTypes().typeRequiresSplitIntoByteArray(D.getType())) { + if (constant && type->isBitIntType() && + CGM.getTypes().typeRequiresSplitIntoByteArray(type)) { // Constants for long _BitInt types are split into individual bytes. // Try to fold these back into an integer constant so it can be stored // properly. - llvm::Type *LoadType = CGM.getTypes().convertTypeForLoadStore( - D.getType(), constant->getType()); + llvm::Type *LoadType = + CGM.getTypes().convertTypeForLoadStore(type, constant->getType()); constant = llvm::ConstantFoldLoadFromConst( constant, LoadType, llvm::APInt::getZero(32), CGM.getDataLayout()); } @@ -1968,8 +1970,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { // It may be that the Init expression uses other uninitialized memory, // but auto-var-init here would not help, as auto-init would get // overwritten by Init. - if (!D.getType()->isScalarType() || capturedByInit || - isAccessedBy(D, Init)) { + if (!type->isScalarType() || capturedByInit || isAccessedBy(D, Init)) { initializeWhatIsTechnicallyUninitialized(Loc); } } diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 44a45413dbc45afdc39c0e9a197cbcbf71ee8ffa..e7dd5fb01ebeded9605191550dff8ba282ba8411 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -21,7 +21,6 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/DiagnosticSema.h" -#include "clang/Basic/TargetBuiltins.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsWebAssembly.h" diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 777b9ae77ad0a142a8ff8f137ae093b4ccb9e450..e658695fb89067a9e10a28a0f8e0883e0dc75545 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -31,22 +31,18 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/SourceManager.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/IR/IntrinsicsWebAssembly.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/MatrixBuilder.h" -#include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" -#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/xxhash.h" #include "llvm/Transforms/Utils/SanitizerStats.h" diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index fef26e7b4ccdbdef79d4586b67a4befbb28c80e2..ac31dff11b585ecb2f8164457d793bead814884c 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -15,12 +15,10 @@ #include "CodeGenModule.h" #include "ConstantEmitter.h" #include "clang/AST/StmtVisitor.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" -#include using namespace clang; using namespace CodeGen; @@ -473,7 +471,7 @@ ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { CGF.ErrorUnsupported(E, "complex expression"); llvm::Type *EltTy = CGF.ConvertType(getComplexType(E->getType())->getElementType()); - llvm::Value *U = llvm::UndefValue::get(EltTy); + llvm::Value *U = llvm::PoisonValue::get(EltTy); return ComplexPairTy(U, U); } @@ -1451,7 +1449,7 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) { CGF.ErrorUnsupported(E, "complex va_arg expression"); llvm::Type *EltTy = CGF.ConvertType(E->getType()->castAs()->getElementType()); - llvm::Value *U = llvm::UndefValue::get(EltTy); + llvm::Value *U = llvm::PoisonValue::get(EltTy); return ComplexPairTy(U, U); } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 287d911e10ba5883cef9ad91770d41d746795415..4ae8a2b22b1bba8a2c0daa0b0cd821d6e28e6c30 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1828,7 +1828,7 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) { CGF.ErrorUnsupported(E, "scalar expression"); if (E->getType()->isVoidType()) return nullptr; - return llvm::UndefValue::get(CGF.ConvertType(E->getType())); + return llvm::PoisonValue::get(CGF.ConvertType(E->getType())); } Value * diff --git a/clang/lib/CodeGen/CGGPUBuiltin.cpp b/clang/lib/CodeGen/CGGPUBuiltin.cpp index 84adf29e8db87eb1b0995254af1ff2f3afc454f7..c133b5f3c0293240ba172f84b62534be26f9562f 100644 --- a/clang/lib/CodeGen/CGGPUBuiltin.cpp +++ b/clang/lib/CodeGen/CGGPUBuiltin.cpp @@ -15,7 +15,6 @@ #include "clang/Basic/Builtins.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Instruction.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Transforms/Utils/AMDGPUEmitPrintf.h" using namespace clang; diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 28da353ff2d78d2b028f926913b554d5eb575ccb..98d98e2d97e888432caeda21d9393824ef18053b 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -23,7 +23,6 @@ #include "clang/Basic/Diagnostic.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/CodeGenABITypes.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/ObjCARCUtil.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/IR/Constants.h" diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index d6f5f2a43cf51b20d3d765b7c571c9505d44a046..cfc92be393940d5f4ff40c5935350f4953ca48c9 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -26,7 +26,6 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtObjC.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "llvm/ADT/SmallVector.h" diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 7caf801d22e0b114e29f1754d7d85fccdc094a6c..7b85dcc2c7984fa821e59a2fa8221652abaedba6 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -25,14 +25,12 @@ #include "clang/AST/StmtObjC.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/LangOptions.h" -#include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/UniqueVector.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IntrinsicInst.h" diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index d449b8e46f9e856a8f552220f0df3d2f2f17266e..7b2f36c08c79fb85c58666f2f610579f2e7ba7fb 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -23,14 +23,10 @@ #include "clang/AST/OpenMPClause.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/BitmaskEnum.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/SourceManager.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SetOperations.h" -#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Bitcode/BitcodeReader.h" @@ -40,7 +36,6 @@ #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Value.h" #include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 598b946ad88dbbf41533aef4f9416eac749936b7..756f0482b8ea72947f09c95ebb4151ea45317e78 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -21,7 +21,6 @@ #include "clang/Basic/Cuda.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h" -#include "llvm/Support/MathExtras.h" using namespace clang; using namespace CodeGen; @@ -2301,9 +2300,11 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(const OMPRequiresDecl *D) { case OffloadArch::GFX909: case OffloadArch::GFX90a: case OffloadArch::GFX90c: + case OffloadArch::GFX9_4_GENERIC: case OffloadArch::GFX940: case OffloadArch::GFX941: case OffloadArch::GFX942: + case OffloadArch::GFX950: case OffloadArch::GFX10_1_GENERIC: case OffloadArch::GFX1010: case OffloadArch::GFX1011: diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 17cdf5df7263a82edec345b8e3aee58fdce5c724..562842133ec60c7921886dea5d55c51b131bd7f1 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -463,6 +463,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { case Stmt::OpenACCLoopConstructClass: EmitOpenACCLoopConstruct(cast(*S)); break; + case Stmt::OpenACCCombinedConstructClass: + EmitOpenACCCombinedConstruct(cast(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 38c154c2c65b10c92b693c4ea4a874153b0eee24..7faf6821a6cdc60739252246b91bd5d554fac76e 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -20,7 +20,6 @@ #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "llvm/IR/IntrinsicInst.h" -#include "llvm/Support/Format.h" #include "llvm/Transforms/Utils/Cloning.h" #include #include diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp index 3f10d68f8c5d45fc93b9be59159819c4fabfe989..aad286f3de53c570c647f5b5891d4e204ddcd17a 100644 --- a/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -21,8 +21,6 @@ #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/PreprocessorOptions.h" using namespace clang; using namespace CodeGen; diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index c9f9b688d0d8a218f406a590e0198c812e932464..cc927f44e0326e6382eb8b5e02ab3f23d7972045 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -25,8 +25,6 @@ #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTWriter.h" @@ -50,7 +48,6 @@ #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" #include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/YAMLTraits.h" #include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/Utils/Cloning.h" diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 6ead45793742d6c8de0b77ad77847028356ffc40..ef6bb4f049d6e8510bd0620470689935d1043e8f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -43,7 +43,6 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Operator.h" #include "llvm/Support/CRC.h" #include "llvm/Support/xxhash.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" @@ -487,7 +486,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { if (IndirectBranch) { llvm::PHINode *PN = cast(IndirectBranch->getAddress()); if (PN->getNumIncomingValues() == 0) { - PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType())); + PN->replaceAllUsesWith(llvm::PoisonValue::get(PN->getType())); PN->eraseFromParent(); } } @@ -636,7 +635,9 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl *FD, CGM.GenKernelArgMetadata(Fn, FD, this); - if (!getLangOpts().OpenCL) + if (!(getLangOpts().OpenCL || + (getLangOpts().CUDA && + getContext().getTargetInfo().getTriple().isSPIRV()))) return; if (const VecTypeHintAttr *A = FD->getAttr()) { @@ -1023,6 +1024,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, } if (FD && (getLangOpts().OpenCL || + (getLangOpts().CUDA && + getContext().getTargetInfo().getTriple().isSPIRV()) || ((getLangOpts().HIP || getLangOpts().OffloadViaLLVM) && getLangOpts().CUDAIsDevice))) { // Add metadata for a kernel function. @@ -1107,8 +1110,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // Create a marker to make it easy to insert allocas into the entryblock // later. Don't create this with the builder, because we don't want it // folded. - llvm::Value *Undef = llvm::UndefValue::get(Int32Ty); - AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "allocapt", EntryBB); + llvm::Value *Poison = llvm::PoisonValue::get(Int32Ty); + AllocaInsertPt = new llvm::BitCastInst(Poison, Int32Ty, "allocapt", EntryBB); ReturnBlock = getJumpDestInCurrentScope("return"); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 6e4064474a8c90d1139ecff16030f8669e89ef18..3e67496b59cc95184457eb6c5c663ebb5b994fab 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4087,6 +4087,13 @@ public: EmitStmt(S.getLoop()); } + void EmitOpenACCCombinedConstruct(const OpenACCCombinedConstruct &S) { + // TODO OpenACC: Implement this. It is currently implemented as a 'no-op', + // simply emitting its loop, but in the future we will implement + // some sort of IR. + EmitStmt(S.getLoop()); + } + //===--------------------------------------------------------------------===// // LValue Expression Emission //===--------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index ba376f9ecfacde7359471de304c207dae8772a27..b854eeb62a80ce84d0d21c6df49f3eb83a979cb2 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -38,13 +38,10 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/CharInfo.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/Diagnostic.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" -#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/CodeGen/BackendUtil.h" @@ -55,7 +52,6 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DataLayout.h" @@ -737,7 +733,7 @@ void CodeGenModule::checkAliases() { for (const GlobalDecl &GD : Aliases) { StringRef MangledName = getMangledName(GD); llvm::GlobalValue *Alias = GetGlobalValue(MangledName); - Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType())); + Alias->replaceAllUsesWith(llvm::PoisonValue::get(Alias->getType())); Alias->eraseFromParent(); } } @@ -1217,6 +1213,9 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-with-bkey", 1); + if (LangOpts.PointerAuthELFGOT) + getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1); + if (getTriple().isOSLinux()) { assert(getTriple().isOSBinFormatELF()); using namespace llvm::ELF; @@ -4903,6 +4902,52 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) { return nullptr; } +static void setWindowsItaniumDLLImport(CodeGenModule &CGM, bool Local, + llvm::Function *F, StringRef Name) { + // In Windows Itanium environments, try to mark runtime functions + // dllimport. For Mingw and MSVC, don't. We don't really know if the user + // will link their standard library statically or dynamically. Marking + // functions imported when they are not imported can cause linker errors + // and warnings. + if (!Local && CGM.getTriple().isWindowsItaniumEnvironment() && + !CGM.getCodeGenOpts().LTOVisibilityPublicStd) { + const FunctionDecl *FD = GetRuntimeFunctionDecl(CGM.getContext(), Name); + if (!FD || FD->hasAttr()) { + F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + F->setLinkage(llvm::GlobalValue::ExternalLinkage); + } + } +} + +llvm::FunctionCallee CodeGenModule::CreateRuntimeFunction( + QualType ReturnTy, ArrayRef ArgTys, StringRef Name, + llvm::AttributeList ExtraAttrs, bool Local, bool AssumeConvergent) { + if (AssumeConvergent) { + ExtraAttrs = + ExtraAttrs.addFnAttribute(VMContext, llvm::Attribute::Convergent); + } + + QualType FTy = Context.getFunctionType(ReturnTy, ArgTys, + FunctionProtoType::ExtProtoInfo()); + const CGFunctionInfo &Info = getTypes().arrangeFreeFunctionType( + Context.getCanonicalType(FTy).castAs()); + auto *ConvTy = getTypes().GetFunctionType(Info); + llvm::Constant *C = GetOrCreateLLVMFunction( + Name, ConvTy, GlobalDecl(), /*ForVTable=*/false, + /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs); + + if (auto *F = dyn_cast(C)) { + if (F->empty()) { + SetLLVMFunctionAttributes(GlobalDecl(), Info, F, /*IsThunk*/ false); + // FIXME: Set calling-conv properly in ExtProtoInfo + F->setCallingConv(getRuntimeCC()); + setWindowsItaniumDLLImport(*this, Local, F, Name); + setDSOLocal(F); + } + } + return {ConvTy, C}; +} + /// CreateRuntimeFunction - Create a new runtime function with the specified /// type and name. llvm::FunctionCallee @@ -4922,24 +4967,12 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, if (auto *F = dyn_cast(C)) { if (F->empty()) { F->setCallingConv(getRuntimeCC()); - - // In Windows Itanium environments, try to mark runtime functions - // dllimport. For Mingw and MSVC, don't. We don't really know if the user - // will link their standard library statically or dynamically. Marking - // functions imported when they are not imported can cause linker errors - // and warnings. - if (!Local && getTriple().isWindowsItaniumEnvironment() && - !getCodeGenOpts().LTOVisibilityPublicStd) { - const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name); - if (!FD || FD->hasAttr()) { - F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); - F->setLinkage(llvm::GlobalValue::ExternalLinkage); - } - } + setWindowsItaniumDLLImport(*this, Local, F, Name); setDSOLocal(F); // FIXME: We should use CodeGenModule::SetLLVMFunctionAttributes() instead // of trying to approximate the attributes using the LLVM function - // signature. This requires revising the API of CreateRuntimeFunction(). + // signature. The other overload of CreateRuntimeFunction does this; it + // should be used for new code. markRegisterParameterAttributes(F); } } @@ -5539,7 +5572,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, } } else { ErrorUnsupported(D, "static initializer"); - Init = llvm::UndefValue::get(getTypes().ConvertType(T)); + Init = llvm::PoisonValue::get(getTypes().ConvertType(T)); } } else { Init = Initializer; diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 8d5787769382f6858a53ff33aa12c3ef590e0219..741b0f17da6584d5f675ffd9f70dac357a7e7951 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1247,11 +1247,23 @@ public: /// Create or return a runtime function declaration with the specified type /// and name. If \p AssumeConvergent is true, the call will have the /// convergent attribute added. + /// + /// For new code, please use the overload that takes a QualType; it sets + /// function attributes more accurately. llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs = llvm::AttributeList(), bool Local = false, bool AssumeConvergent = false); + /// Create or return a runtime function declaration with the specified type + /// and name. If \p AssumeConvergent is true, the call will have the + /// convergent attribute added. + llvm::FunctionCallee + CreateRuntimeFunction(QualType ReturnTy, ArrayRef ArgTys, + StringRef Name, + llvm::AttributeList ExtraAttrs = llvm::AttributeList(), + bool Local = false, bool AssumeConvergent = false); + /// Create a new runtime global variable with the specified type and name. llvm::Constant *CreateRuntimeVariable(llvm::Type *Ty, StringRef Name); diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 820bb521ccf850e2f3c906be94e58d0d5ba4050d..17d7902f0cfbc7558b9d5709ba3ce3f95994aeb1 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -19,7 +19,6 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MD5.h" #include diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index ec175b7fabe61f7e19acdc74b34c305d196268e2..c31579e8323174a58a2521c506d4ca4ba8c03b95 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -25,8 +25,6 @@ #include "clang/AST/RecordLayout.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/TargetInfo.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 45518736a2ac38e25f887a4bab3e190ec40bb61c..96c89b2728e5b7befa8613c75ed816fd99697b3f 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -14,8 +14,6 @@ #include "CodeGenFunction.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Diagnostic.h" -#include "clang/Basic/FileManager.h" -#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallSet.h" @@ -23,7 +21,6 @@ #include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" -#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 9b3c2f1b2af67726b612dbc7ddd69dbf7cd3c5c7..8cbd09d02c7556eb88eac91755a4a94e5d4fbd4a 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -23,7 +23,6 @@ #include "CGVTables.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" -#include "ConstantEmitter.h" #include "TargetInfo.h" #include "clang/AST/Attr.h" #include "clang/AST/Mangle.h" diff --git a/clang/lib/CodeGen/LinkInModulesPass.cpp b/clang/lib/CodeGen/LinkInModulesPass.cpp index 44b2df52f001a7bfeb46a3b75df18c03c14e604f..6f168ea4a53dd883fb29a2a77c4ec3b0b469d2c3 100644 --- a/clang/lib/CodeGen/LinkInModulesPass.cpp +++ b/clang/lib/CodeGen/LinkInModulesPass.cpp @@ -14,10 +14,6 @@ #include "LinkInModulesPass.h" #include "BackendConsumer.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" - using namespace llvm; LinkInModulesPass::LinkInModulesPass(clang::BackendConsumer *BC) : BC(BC) {} diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 3802dc8bcafc49b687b146868c887ba1def423a6..d587daac5a88a9ffdbfb2ac14ad1b4cee96698ef 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -431,6 +431,7 @@ public: bool usesThreadWrapperFunction(const VarDecl *VD) const override { return getContext().getLangOpts().isCompatibleWithMSVC( LangOptions::MSVC2019_5) && + CGM.getCodeGenOpts().TlsGuards && (!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD)); } LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp index 3a1f745d9ed777f8af9e644a9cfe0fc06e97c539..71745480706ed6836fea3e02ca472170ea1555bd 100644 --- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp @@ -21,15 +21,12 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Bitstream/BitstreamReader.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/COFF.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Path.h" #include #include diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp index 5b212a163611dc6d665a69e79476d2b2f9c510ce..c1a6b223480a19e0bfbb95727854b73fce286f2a 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.cpp +++ b/clang/lib/CodeGen/SanitizerMetadata.cpp @@ -13,9 +13,6 @@ #include "CodeGenModule.h" #include "clang/AST/Attr.h" #include "clang/AST/Type.h" -#include "clang/Basic/SourceManager.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/IR/Constants.h" using namespace clang; using namespace CodeGen; diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index ab2e2bd0b30646557c91f26e8353412990cbd5db..0873896df213e823c0d0aed633c123f49beff80f 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -15,7 +15,6 @@ #include "CodeGenModule.h" #include "TargetInfo.h" #include "clang/Basic/TargetInfo.h" -#include using namespace clang; using namespace CodeGen; diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index ad077d5bbfa69ab189b4e8fef489a2d8dd0b0bcb..4d4080507175c2487bedef969986dc1913791781 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -10,13 +10,10 @@ #include "clang/Basic/LLVM.h" #include "clang/Driver/Action.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptSpecifier.h" #include "llvm/Option/Option.h" diff --git a/clang/lib/Driver/Distro.cpp b/clang/lib/Driver/Distro.cpp index 3d1bce027f664d9dfd717e29af9641e3400e2652..3cc79535de8dab172498c5852b434aa3c4002151 100644 --- a/clang/lib/Driver/Distro.cpp +++ b/clang/lib/Driver/Distro.cpp @@ -8,7 +8,6 @@ #include "clang/Driver/Distro.h" #include "clang/Basic/LLVM.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorOr.h" diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index c07bca2841992cc42c036449d5fce8529df893c8..8b5669cb8258188472b260ace01c0b9aad20f622 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -56,7 +56,6 @@ #include "clang/Config/config.h" #include "clang/Driver/Action.h" #include "clang/Driver/Compilation.h" -#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/InputInfo.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" diff --git a/clang/lib/Driver/DriverOptions.cpp b/clang/lib/Driver/DriverOptions.cpp index b25801a8f3f4940a170085d3e06d454ae51758d6..053e7f1c6404fe72de35f527112343c315af3d7d 100644 --- a/clang/lib/Driver/DriverOptions.cpp +++ b/clang/lib/Driver/DriverOptions.cpp @@ -7,9 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Driver/Options.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Option/OptTable.h" -#include "llvm/Option/Option.h" #include using namespace clang::driver; diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index fe2f7242b04a5132a5548c184ff92c1b6c59138a..ae2f1cd1f56c99642fd944cad9aeb7b44108aa20 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -9,7 +9,6 @@ #include "clang/Driver/Job.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/InputInfo.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -26,7 +25,6 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" -#include #include #include #include diff --git a/clang/lib/Driver/Multilib.cpp b/clang/lib/Driver/Multilib.cpp index c56417c6f6d0b06bb6dbf453f07a61607cf74c1f..0207e0f2eb2dedd97bc93fb60bc5b4a392f3c35d 100644 --- a/clang/lib/Driver/Multilib.cpp +++ b/clang/lib/Driver/Multilib.cpp @@ -8,15 +8,11 @@ #include "clang/Driver/Multilib.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/Version.h" #include "clang/Driver/Driver.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Path.h" #include "llvm/Support/Regex.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/YAMLParser.h" diff --git a/clang/lib/Driver/MultilibBuilder.cpp b/clang/lib/Driver/MultilibBuilder.cpp index 4b365a164c458639989c0233bdbd76a5d2bfe637..4fbe9d9047bde5dede55551fda400613111080e0 100644 --- a/clang/lib/Driver/MultilibBuilder.cpp +++ b/clang/lib/Driver/MultilibBuilder.cpp @@ -8,7 +8,6 @@ #include "clang/Driver/MultilibBuilder.h" #include "ToolChains/CommonArgs.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Path.h" #include "llvm/Support/Regex.h" diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp index 687a38333e12872ec002cdf5cbd845579970f898..87d7303d938c909faafcf7a5e32796a114de7858 100644 --- a/clang/lib/Driver/OffloadBundler.cpp +++ b/clang/lib/Driver/OffloadBundler.cpp @@ -17,7 +17,6 @@ #include "clang/Driver/OffloadBundler.h" #include "clang/Basic/Cuda.h" #include "clang/Basic/TargetID.h" -#include "clang/Basic/Version.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 89f1215afd0c814ad887658cc748f07f80a21b92..1abfe8fd92807e56e4e0c21744f0c7543e7b9242 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -6,13 +6,10 @@ // //===----------------------------------------------------------------------===// #include "clang/Driver/SanitizerArgs.h" -#include "ToolChains/CommonArgs.h" #include "clang/Basic/Sanitizers.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Path.h" @@ -68,9 +65,9 @@ static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress | static const SanitizerMask NeedsLTO = SanitizerKind::CFI; static const SanitizerMask TrappingSupported = (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer | - SanitizerKind::Nullability | SanitizerKind::LocalBounds | - SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | - SanitizerKind::ObjCCast; + SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | + SanitizerKind::LocalBounds | SanitizerKind::CFI | + SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; static const SanitizerMask TrappingDefault = SanitizerKind::CFI; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 646dbc0faf5a9ff7944e440571b1eb8dee853b0e..0d426a467e9a3b1b28421d91b8fd6694673c2263 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -19,13 +19,11 @@ #include "clang/Config/config.h" #include "clang/Driver/Action.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/InputInfo.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/XRayArgs.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index f083e40df13144965b163cfb5f002df409bea118..1e2ac4e501bafd1a09e5813ea7ba29036df8005c 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -135,15 +135,21 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef March, return true; } -static bool -getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu, - const ArgList &Args, - llvm::AArch64::ExtensionSet &Extensions) { +static bool getAArch64ArchFeaturesFromMcpu( + const Driver &D, StringRef Mcpu, const ArgList &Args, + llvm::AArch64::ExtensionSet &Extensions, std::vector &Features) { StringRef CPU; std::string McpuLowerCase = Mcpu.lower(); if (!DecodeAArch64Mcpu(D, McpuLowerCase, CPU, Extensions)) return false; + if (Mcpu == "native") { + llvm::StringMap HostFeatures = llvm::sys::getHostCPUFeatures(); + for (auto &[Feature, Enabled] : HostFeatures) { + Features.push_back(Args.MakeArgString((Enabled ? "+" : "-") + Feature)); + } + } + return true; } @@ -210,11 +216,11 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args, Extensions); else if ((A = Args.getLastArg(options::OPT_mcpu_EQ))) - success = - getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions); + success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions, + Features); else if (isCPUDeterminedByTriple(Triple)) success = getAArch64ArchFeaturesFromMcpu( - D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions); + D, getAArch64TargetCPU(Args, Triple, A), Args, Extensions, Features); else // Default to 'A' profile if the architecture is not specified. success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions); diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index 0489911ecd9deea5061701fff2ac7f2c2aa8fa25..e6ee2317a160cce02dcf1dbf3f558714a84b328b 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -908,6 +908,10 @@ fp16_fml_fallthrough: if (VersionNum < 6 || Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) Features.push_back("+strict-align"); + } else if (Triple.getVendor() == llvm::Triple::Apple && + Triple.isOSBinFormatMachO()) { + // Firmwares on Apple platforms are strict-align by default. + Features.push_back("+strict-align"); } else if (VersionNum < 7 || Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m || diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp index e69a5562137ccd20a5aade6519d5b6558980a299..987db4638fca88286af46f013af5139c41949a42 100644 --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp @@ -135,10 +135,15 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, Features.push_back("+lsx"); std::string ArchName; - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) - ArchName = A->getValue(); + const Arg *MArch = Args.getLastArg(options::OPT_march_EQ); + if (MArch) + ArchName = MArch->getValue(); ArchName = postProcessTargetCPUString(ArchName, Triple); llvm::LoongArch::getArchFeatures(ArchName, Features); + if (MArch && StringRef(MArch->getValue()) == "native") + for (auto &F : llvm::sys::getHostCPUFeatures()) + Features.push_back( + Args.MakeArgString((F.second ? "+" : "-") + F.first())); // Select floating-point features determined by -mdouble-float, // -msingle-float, -msoft-float and -mfpu. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1d5f3578b1f4bfb083f78f515a6344ed61fb7620..564243dc09dbb5fff35ac42c5792bab75f82aee6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -44,7 +44,6 @@ #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Config/llvm-config.h" #include "llvm/Frontend/Debug/Options.h" @@ -1342,6 +1341,7 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { return false; case llvm::Triple::hexagon: + case llvm::Triple::msp430: case llvm::Triple::ppcle: case llvm::Triple::ppc64le: case llvm::Triple::riscv32: @@ -7354,6 +7354,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, (!IsWindowsMSVC || IsMSVC2015Compatible))) CmdArgs.push_back("-fno-threadsafe-statics"); + if (!Args.hasFlag(options::OPT_fms_tls_guards, options::OPT_fno_ms_tls_guards, + true)) + CmdArgs.push_back("-fno-ms-tls-guards"); + // Add -fno-assumptions, if it was specified. if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions, true)) diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 0d50d46c2cfa6ad158fa7f6751f7d21127c789f7..2c79c25b4366f491d52447b38386de470c54f23b 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1763,18 +1763,13 @@ Arg *tools::getLastProfileUseArg(const ArgList &Args) { Arg *tools::getLastProfileSampleUseArg(const ArgList &Args) { auto *ProfileSampleUseArg = Args.getLastArg( - options::OPT_fprofile_sample_use, options::OPT_fprofile_sample_use_EQ, - options::OPT_fauto_profile, options::OPT_fauto_profile_EQ, - options::OPT_fno_profile_sample_use, options::OPT_fno_auto_profile); - - if (ProfileSampleUseArg && - (ProfileSampleUseArg->getOption().matches( - options::OPT_fno_profile_sample_use) || - ProfileSampleUseArg->getOption().matches(options::OPT_fno_auto_profile))) + options::OPT_fprofile_sample_use_EQ, options::OPT_fno_profile_sample_use); + + if (ProfileSampleUseArg && (ProfileSampleUseArg->getOption().matches( + options::OPT_fno_profile_sample_use))) return nullptr; - return Args.getLastArg(options::OPT_fprofile_sample_use_EQ, - options::OPT_fauto_profile_EQ); + return Args.getLastArg(options::OPT_fprofile_sample_use_EQ); } const char *tools::RelocationModelName(llvm::Reloc::Model Model) { @@ -2725,7 +2720,7 @@ void tools::checkAMDGPUCodeObjectVersion(const Driver &D, unsigned tools::getAMDGPUCodeObjectVersion(const Driver &D, const llvm::opt::ArgList &Args) { - unsigned CodeObjVer = 4; // default + unsigned CodeObjVer = 5; // default if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) StringRef(CodeObjArg->getValue()).getAsInteger(0, CodeObjVer); return CodeObjVer; diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index f9d2fdffe3b2fc0aab6041e6ca1e58bf7ab458bc..11070c23c75f4abcbc2d1e58ac7f3312cd174959 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -414,6 +414,9 @@ void Flang::addTargetOptions(const ArgList &Args, case llvm::Triple::ppc64le: AddPPCTargetArgs(Args, CmdArgs); break; + case llvm::Triple::loongarch64: + getTargetFeatures(D, Triple, Args, CmdArgs, /*ForAs*/ false); + break; } if (Arg *A = Args.getLastArg(options::OPT_fveclib)) { diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index e51daca5025a80a4330ed310d5946076dd09075d..963de81027ca9fc22557110ac1800803166314a5 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -188,6 +188,9 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, << A->getSpelling() << GuardArgs; } + if (Args.hasArg(options::OPT_fms_hotpatch)) + CmdArgs.push_back("--functionpadmin"); + CmdArgs.push_back("-o"); const char *OutputFile = Output.getFilename(); // GCC implicitly adds an .exe extension if it is given an output file name diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp index df43da93d77555c65df1db96e2436ffd1cc034a4..c2eeb8f513066fec5467474b11f68c940d48a5ea 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -183,6 +183,7 @@ void tools::PS4cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString(Twine("-lto-debug-options=") + LTOArgs)); + // Sanitizer runtimes must be supplied before all other objects and libs. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); @@ -303,10 +304,12 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, // with the SDK. The scripts are inside /target/lib, which is // added as a search path elsewhere. // "PRX" has long stood for "PlayStation Relocatable eXecutable". - CmdArgs.push_back("--default-script"); - CmdArgs.push_back(Static ? "static.script" - : Shared ? "prx.script" - : "main.script"); + if (!Args.hasArgNoClaim(options::OPT_T)) { + CmdArgs.push_back("--default-script"); + CmdArgs.push_back(Static ? "static.script" + : Shared ? "prx.script" + : "main.script"); + } } if (Static) @@ -358,9 +361,6 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (StringRef Jobs = getLTOParallelism(Args, D); !Jobs.empty()) AddLTOFlag(Twine("jobs=") + Jobs); - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) - TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); - TC.AddFilePathLibArgs(Args, CmdArgs); Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_s, options::OPT_t}); @@ -368,17 +368,63 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); - AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + // Sanitizer runtimes must be supplied before all other objects and libs. + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) + TC.addSanitizerArgs(Args, CmdArgs, "-l", ""); - if (Args.hasArg(options::OPT_pthread)) { - CmdArgs.push_back("-lpthread"); + const bool AddStartFiles = + !Relocatable && + !Args.hasArg(options::OPT_nostartfiles, options::OPT_nostdlib); + + auto AddCRTObject = [&](const char *Name) { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath(Name))); + }; + + if (AddStartFiles) { + if (!Shared) + AddCRTObject("crt1.o"); + AddCRTObject("crti.o"); + AddCRTObject(Shared ? "crtbeginS.o" + : Static ? "crtbeginT.o" + : "crtbegin.o"); } - if (UseJMC) { - CmdArgs.push_back("--push-state"); - CmdArgs.push_back("--whole-archive"); - CmdArgs.push_back("-lSceJmc_nosubmission"); - CmdArgs.push_back("--pop-state"); + AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + + if (!Relocatable && + !Args.hasArg(options::OPT_nodefaultlibs, options::OPT_nostdlib)) { + + if (UseJMC) { + CmdArgs.push_back("--push-state"); + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back("-lSceJmc_nosubmission"); + CmdArgs.push_back("--pop-state"); + } + + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-lpthread"); + + if (Static) { + if (!Args.hasArg(options::OPT_nostdlibxx)) + CmdArgs.push_back("-lstdc++"); + if (!Args.hasArg(options::OPT_nolibc)) { + CmdArgs.push_back("-lm"); + CmdArgs.push_back("-lc"); + } + + CmdArgs.push_back("-lcompiler_rt"); + CmdArgs.push_back("-lkernel"); + } else { + // The C and C++ libraries are combined. + if (!Args.hasArg(options::OPT_nolibc, options::OPT_nostdlibxx)) + CmdArgs.push_back("-lc_stub_weak"); + + CmdArgs.push_back("-lkernel_stub_weak"); + } + } + if (AddStartFiles) { + AddCRTObject(Shared ? "crtendS.o" : "crtend.o"); + AddCRTObject("crtn.o"); } if (Args.hasArg(options::OPT_fuse_ld_EQ)) { diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index b14aac0f0ce015eb66c32f28b3cb149cef5e6400..eaca74a7b5529262e5ff820a949174fbb3b08837 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -8,12 +8,9 @@ #include "clang/Driver/Types.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/Options.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Option/Arg.h" #include #include diff --git a/clang/lib/Driver/XRayArgs.cpp b/clang/lib/Driver/XRayArgs.cpp index adb61544c0f9248f0580ebaf82a73910c497e9c5..de5c38ebc3abbda772e22c5135bad9ec60cf7d35 100644 --- a/clang/lib/Driver/XRayArgs.cpp +++ b/clang/lib/Driver/XRayArgs.cpp @@ -8,13 +8,10 @@ #include "clang/Driver/XRayArgs.h" #include "ToolChains/CommonArgs.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/VirtualFileSystem.h" diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 269cbef2720792c6d7aa42506f8783fedb9779b3..bc5239209f3aabf7a5f85751ca97dde34cded64d 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1554,7 +1554,7 @@ private: }; if (IsInstancePort()) - Tok->setFinalizedType(TT_VerilogInstancePortLParen); + Tok->setType(TT_VerilogInstancePortLParen); } if (!parseParens()) @@ -1730,7 +1730,7 @@ private: Tok->setType(TT_InheritanceComma); break; case Context::VerilogInstancePortList: - Tok->setFinalizedType(TT_VerilogInstancePortComma); + Tok->setType(TT_VerilogInstancePortComma); break; default: if (Style.isVerilog() && Contexts.size() == 1 && diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 5f1dd38ef1eb3bf38e341537064afe6cb564ee50..c182aaf0876d1bce8bf615558523a033663f9e41 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -4441,7 +4441,8 @@ unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() { Prev->setFinalizedType(TT_VerilogDimensionedTypeName); parseSquare(); } else if (Keywords.isVerilogIdentifier(*FormatTok) || - FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) { + FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon, + Keywords.kw_automatic, tok::kw_static)) { nextToken(); } else { break; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index ecc6782c7cb4fb809e5891250cb87f62c632ae96..fbfc305ca06a041f30e4d14d40945e8427ee536e 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -332,23 +332,20 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, } } -void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client, +void CompilerInstance::createDiagnostics(llvm::vfs::FileSystem &VFS, + DiagnosticConsumer *Client, bool ShouldOwnClient) { - Diagnostics = createDiagnostics( - &getDiagnosticOpts(), Client, ShouldOwnClient, &getCodeGenOpts(), - FileMgr ? FileMgr->getVirtualFileSystemPtr() : nullptr); + Diagnostics = createDiagnostics(VFS, &getDiagnosticOpts(), Client, + ShouldOwnClient, &getCodeGenOpts()); } IntrusiveRefCntPtr CompilerInstance::createDiagnostics( - DiagnosticOptions *Opts, DiagnosticConsumer *Client, bool ShouldOwnClient, - const CodeGenOptions *CodeGenOpts, - llvm::IntrusiveRefCntPtr VFS) { + llvm::vfs::FileSystem &VFS, DiagnosticOptions *Opts, + DiagnosticConsumer *Client, bool ShouldOwnClient, + const CodeGenOptions *CodeGenOpts) { IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr - Diags(new DiagnosticsEngine(DiagID, Opts)); - - if (!VFS) - VFS = llvm::vfs::getRealFileSystem(); + IntrusiveRefCntPtr Diags( + new DiagnosticsEngine(DiagID, Opts)); // Create the diagnostic client for reporting errors or for // implementing -verify. @@ -372,7 +369,7 @@ IntrusiveRefCntPtr CompilerInstance::createDiagnostics( Opts->DiagnosticSerializationFile); // Configure our handling of diagnostics. - ProcessWarningOptions(*Diags, *Opts, *VFS); + ProcessWarningOptions(*Diags, *Opts, VFS); return Diags; } @@ -1240,9 +1237,10 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, auto &Inv = *Invocation; Instance.setInvocation(std::move(Invocation)); - Instance.createDiagnostics(new ForwardingDiagnosticConsumer( - ImportingInstance.getDiagnosticClient()), - /*ShouldOwnClient=*/true); + Instance.createDiagnostics( + ImportingInstance.getVirtualFileSystem(), + new ForwardingDiagnosticConsumer(ImportingInstance.getDiagnosticClient()), + /*ShouldOwnClient=*/true); if (llvm::is_contained(DiagOpts.SystemHeaderWarningsModules, ModuleName)) Instance.getDiagnostics().setSuppressSystemWarnings(false); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 7963fa2aa85fe30ce4382d0de1750fa4a3232e0f..91533d6ffa0b60f87fbac00e4e8552f022e8904a 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3452,6 +3452,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_init_fini); if (Opts.PointerAuthInitFiniAddressDiscrimination) GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination); + if (Opts.PointerAuthELFGOT) + GenerateArg(Consumer, OPT_fptrauth_elf_got); } static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, @@ -3472,6 +3474,7 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini); Opts.PointerAuthInitFiniAddressDiscrimination = Args.hasArg(OPT_fptrauth_init_fini_address_discrimination); + Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got); } /// Check if input file kind and language standard are compatible. diff --git a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp index 638757a2450240b365f66756c9693e428733f8c7..d0b855fff2534c7cb691bad5dea41896c10a7af7 100644 --- a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Host.h" using namespace clang; using namespace llvm::opt; @@ -32,7 +33,9 @@ clang::createInvocation(ArrayRef ArgList, assert(!ArgList.empty()); auto Diags = Opts.Diags ? std::move(Opts.Diags) - : CompilerInstance::createDiagnostics(new DiagnosticOptions); + : CompilerInstance::createDiagnostics( + Opts.VFS ? *Opts.VFS : *llvm::vfs::getRealFileSystem(), + new DiagnosticOptions); SmallVector Args(ArgList); diff --git a/clang/lib/Frontend/Rewrite/FrontendActions.cpp b/clang/lib/Frontend/Rewrite/FrontendActions.cpp index 6e1f949f543a51eae65004702bb5051c12521644..5d2e1d78770959c830b667b11bc7a8a73aac1ff3 100644 --- a/clang/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/clang/lib/Frontend/Rewrite/FrontendActions.cpp @@ -247,6 +247,7 @@ public: Instance.setInvocation( std::make_shared(CI.getInvocation())); Instance.createDiagnostics( + CI.getVirtualFileSystem(), new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), /*ShouldOwnClient=*/true); Instance.getFrontendOpts().DisableFree = false; diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 30c07e035f0d45ffddaeef846d483af3bf8cc70e..d3289e0097b7b4e2c80410de26f223f5980bb439 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -147,8 +147,11 @@ set(x86_files adxintrin.h ammintrin.h amxavx512intrin.h + amxbf16transposeintrin.h amxcomplexintrin.h + amxcomplextransposeintrin.h amxfp16intrin.h + amxfp16transposeintrin.h amxfp8intrin.h amxintrin.h amxmovrsintrin.h @@ -230,6 +233,7 @@ set(x86_files movdirintrin.h movrs_avx10_2_512intrin.h movrs_avx10_2intrin.h + movrsintrin.h mwaitxintrin.h nmmintrin.h pconfigintrin.h diff --git a/clang/lib/Headers/amdgpuintrin.h b/clang/lib/Headers/amdgpuintrin.h index f4f90b394522d61b7900730f1192f7f63419258e..720674a85f52cf73bded1f95e42cefca4a0943c8 100644 --- a/clang/lib/Headers/amdgpuintrin.h +++ b/clang/lib/Headers/amdgpuintrin.h @@ -24,11 +24,11 @@ _Pragma("omp begin declare target device_type(nohost)"); _Pragma("omp begin declare variant match(device = {arch(amdgcn)})"); // Type aliases to the address spaces used by the AMDGPU backend. -#define __gpu_private __attribute__((opencl_private)) -#define __gpu_constant __attribute__((opencl_constant)) -#define __gpu_local __attribute__((opencl_local)) -#define __gpu_global __attribute__((opencl_global)) -#define __gpu_generic __attribute__((opencl_generic)) +#define __gpu_private __attribute__((address_space(5))) +#define __gpu_constant __attribute__((address_space(4))) +#define __gpu_local __attribute__((address_space(3))) +#define __gpu_global __attribute__((address_space(1))) +#define __gpu_generic __attribute__((address_space(0))) // Attribute to declare a function as a kernel. #define __gpu_kernel __attribute__((amdgpu_kernel, visibility("protected"))) @@ -160,14 +160,14 @@ __gpu_shuffle_idx_u64(uint64_t __lane_mask, uint32_t __idx, uint64_t __x) { // Returns true if the flat pointer points to CUDA 'shared' memory. _DEFAULT_FN_ATTRS static __inline__ bool __gpu_is_ptr_local(void *ptr) { - return __builtin_amdgcn_is_shared( - (void __attribute__((address_space(0))) *)((void __gpu_generic *)ptr)); + return __builtin_amdgcn_is_shared((void __attribute__((address_space(0))) *)(( + void [[clang::opencl_generic]] *)ptr)); } // Returns true if the flat pointer points to CUDA 'local' memory. _DEFAULT_FN_ATTRS static __inline__ bool __gpu_is_ptr_private(void *ptr) { - return __builtin_amdgcn_is_private( - (void __attribute__((address_space(0))) *)((void __gpu_generic *)ptr)); + return __builtin_amdgcn_is_private((void __attribute__(( + address_space(0))) *)((void [[clang::opencl_generic]] *)ptr)); } // Terminates execution of the associated wavefront. diff --git a/clang/lib/Headers/amxbf16transposeintrin.h b/clang/lib/Headers/amxbf16transposeintrin.h new file mode 100644 index 0000000000000000000000000000000000000000..86f09f2ad8db2b255d301a2e85ed1a508bdd9c25 --- /dev/null +++ b/clang/lib/Headers/amxbf16transposeintrin.h @@ -0,0 +1,94 @@ +/*===----- amxbf16transposeintrin.h - AMX-BF16 and AMX-TRANSPOSE ------------=== + * + * 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 __IMMINTRIN_H +#error \ + "Never use directly; use instead." +#endif /* __IMMINTRIN_H */ + +#ifndef __AMX_BF16TRANSPOSEINTRIN_H +#define __AMX_BF16TRANSPOSEINTRIN_H +#ifdef __x86_64__ + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, \ + __target__("amx-bf16,amx-transpose"))) + +/// Compute transpose and dot-product of BF16 (16-bit) floating-point pairs in +/// tiles \a a and \a b, accumulating the intermediate single-precision +/// (32-bit) floating-point elements with elements in \a dst, and store the +/// 32-bit result back to tile \a dst. +/// +/// \headerfile +/// +/// \code +/// void _tile_tdpbf16ps (__tile dst, __tile a, __tile b) +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// tmp := dst.row[m] +/// FOR k := 0 TO (a.colsb / 4) - 1 +/// FOR n := 0 TO (dst.colsb / 4) - 1 +/// tmp.bf32[n] += FP32(a.row[m].bf16[2*k+0]) * +/// FP32(b.row[k].bf16[2*n+0]) +/// tmp.bf32[n] += FP32(a.row[m].bf16[2*k+1]) * +/// FP32(b.row[k].bf16[2*n+1]) +/// ENDFOR +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// ENDFOR +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() +/// \endcode +/// +/// This intrinsic corresponds to the \c TTDPBF16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param a +/// The 1st source tile. Max size is 1024 Bytes. +/// \param b +/// The 2nd source tile. Max size is 1024 Bytes. +#define _tile_tdpbf16ps(dst, a, b) __builtin_ia32_ttdpbf16ps((dst), (a), (b)) + +/// This is internal intrinsic. C/C++ user should avoid calling it directly. +static __inline__ _tile1024i __DEFAULT_FN_ATTRS +_tile_tdpbf16ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_ttdpbf16ps_internal(m, n, k, dst, src1, src2); +} + +/// Compute transpose and dot-product of BF16 (16-bit) floating-point pairs in +/// tiles src0 and src1, accumulating the intermediate single-precision +/// (32-bit) floating-point elements with elements in "dst", and store the +/// 32-bit result back to tile "dst". +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TTDPBF16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src0 +/// The 1st source tile. Max size is 1024 Bytes. +/// \param src1 +/// The 2nd source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static __inline__ void __tile_tdpbf16ps(__tile1024i *dst, __tile1024i src0, + __tile1024i src1) { + dst->tile = _tile_tdpbf16ps_internal(src0.row, src1.col, src0.col, dst->tile, + src0.tile, src1.tile); +} + +#undef __DEFAULT_FN_ATTRS + +#endif /* __x86_64__ */ +#endif /* __AMX_BF16TRANSPOSEINTRIN_H */ diff --git a/clang/lib/Headers/amxcomplextransposeintrin.h b/clang/lib/Headers/amxcomplextransposeintrin.h new file mode 100644 index 0000000000000000000000000000000000000000..11abaf98e93719d2e71e90d4399054a70b1c9504 --- /dev/null +++ b/clang/lib/Headers/amxcomplextransposeintrin.h @@ -0,0 +1,303 @@ +/*===----- amxcomplextransposeintrin.h - AMX-COMPLEX and AMX-TRANSPOSE ------=== + * + * 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 __IMMINTRIN_H +#error \ + "Never use directly; include instead." +#endif // __IMMINTRIN_H + +#ifndef __AMX_COMPLEXTRANSPOSEINTRIN_H +#define __AMX_COMPLEXTRANSPOSEINTRIN_H +#ifdef __x86_64__ + +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, \ + __target__("amx-complex,amx-transpose"))) + +/// Perform matrix multiplication of two tiles containing complex elements and +/// accumulate the results into a packed single precision tile. Each dword +/// element in input tiles \a a and \a b is interpreted as a complex number +/// with FP16 real part and FP16 imaginary part. +/// Calculates the imaginary part of the result. For each possible combination +/// of (transposed column of \a a, column of \a b), it performs a set of +/// multiplication and accumulations on all corresponding complex numbers +/// (one from \a a and one from \a b). The imaginary part of the \a a element +/// is multiplied with the real part of the corresponding \a b element, and +/// the real part of the \a a element is multiplied with the imaginary part +/// of the corresponding \a b elements. The two accumulated results are +/// added, and then accumulated into the corresponding row and column of +/// \a dst. +/// +/// \headerfile +/// +/// \code +/// void _tile_tcmmimfp16ps(__tile dst, __tile a, __tile b); +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// tmp := dst.row[m] +/// FOR k := 0 TO a.rows - 1 +/// FOR n := 0 TO (dst.colsb / 4) - 1 +/// tmp.fp32[n] += FP32(a.row[m].fp16[2*k+0]) * FP32(b.row[k].fp16[2*n+1]) +/// tmp.fp32[n] += FP32(a.row[m].fp16[2*k+1]) * FP32(b.row[k].fp16[2*n+0]) +/// ENDFOR +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// ENDFOR +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() +/// \endcode +/// +/// This intrinsic corresponds to the \c TTCMMIMFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param a +/// The 1st source tile. Max size is 1024 Bytes. +/// \param b +/// The 2nd source tile. Max size is 1024 Bytes. +#define _tile_tcmmimfp16ps(dst, a, b) \ + __builtin_ia32_ttcmmimfp16ps((dst), (a), (b)) + +/// Perform matrix multiplication of two tiles containing complex elements and +/// accumulate the results into a packed single precision tile. Each dword +/// element in input tiles \a a and \a b is interpreted as a complex number +/// with FP16 real part and FP16 imaginary part. +/// Calculates the real part of the result. For each possible combination +/// of (rtransposed colum of \a a, column of \a b), it performs a set of +/// multiplication and accumulations on all corresponding complex numbers +/// (one from \a a and one from \a b). The real part of the \a a element is +/// multiplied with the real part of the corresponding \a b element, and the +/// negated imaginary part of the \a a element is multiplied with the +/// imaginary part of the corresponding \a b elements. The two accumulated +/// results are added, and then accumulated into the corresponding row and +/// column of \a dst. +/// +/// \headerfile +/// +/// \code +/// void _tile_tcmmrlfp16ps(__tile dst, __tile a, __tile b); +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// tmp := dst.row[m] +/// FOR k := 0 TO a.rows - 1 +/// FOR n := 0 TO (dst.colsb / 4) - 1 +/// tmp.fp32[n] += FP32(a.row[m].fp16[2*k+0]) * FP32(b.row[k].fp16[2*n+0]) +/// tmp.fp32[n] += FP32(-a.row[m].fp16[2*k+1]) * FP32(b.row[k].fp16[2*n+1]) +/// ENDFOR +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// ENDFOR +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() +/// \endcode +/// +/// This intrinsic corresponds to the \c TTCMMIMFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param a +/// The 1st source tile. Max size is 1024 Bytes. +/// \param b +/// The 2nd source tile. Max size is 1024 Bytes. +#define _tile_tcmmrlfp16ps(dst, a, b) \ + __builtin_ia32_ttcmmrlfp16ps((dst), (a), (b)) + +/// Perform matrix conjugate transpose and multiplication of two tiles +/// containing complex elements and accumulate the results into a packed +/// single precision tile. Each dword element in input tiles \a a and \a b +/// is interpreted as a complex number with FP16 real part and FP16 imaginary +/// part. +/// Calculates the imaginary part of the result. For each possible combination +/// of (transposed column of \a a, column of \a b), it performs a set of +/// multiplication and accumulations on all corresponding complex numbers +/// (one from \a a and one from \a b). The negated imaginary part of the \a a +/// element is multiplied with the real part of the corresponding \a b +/// element, and the real part of the \a a element is multiplied with the +/// imaginary part of the corresponding \a b elements. The two accumulated +/// results are added, and then accumulated into the corresponding row and +/// column of \a dst. +/// +/// \headerfile +/// +/// \code +/// void _tile_conjtcmmimfp16ps(__tile dst, __tile a, __tile b); +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// tmp := dst.row[m] +/// FOR k := 0 TO a.rows - 1 +/// FOR n := 0 TO (dst.colsb / 4) - 1 +/// tmp.fp32[n] += FP32(a.row[m].fp16[2*k+0]) * FP32(b.row[k].fp16[2*n+1]) +/// tmp.fp32[n] += FP32(-a.row[m].fp16[2*k+1]) * FP32(b.row[k].fp16[2*n+0]) +/// ENDFOR +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// ENDFOR +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() +/// \endcode +/// +/// This intrinsic corresponds to the \c TCONJTCMMIMFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param a +/// The 1st source tile. Max size is 1024 Bytes. +/// \param b +/// The 2nd source tile. Max size is 1024 Bytes. +#define _tile_conjtcmmimfp16ps(dst, a, b) \ + __builtin_ia32_tconjtcmmimfp16ps((dst), (a), (b)) + +/// Perform conjugate transpose of an FP16-pair of complex elements from \a a +/// and writes the result to \a dst. +/// +/// \headerfile +/// +/// \code +/// void _tile_conjtfp16(__tile dst, __tile a); +/// \endcode +/// +/// \code{.operation} +/// FOR i := 0 TO dst.rows - 1 +/// FOR j := 0 TO (dst.colsb / 4) - 1 +/// tmp.fp16[2*j+0] := a.row[j].fp16[2*i+0] +/// tmp.fp16[2*j+1] := -a.row[j].fp16[2*i+1] +/// ENDFOR +/// write_row_and_zero(dst, i, tmp, dst.colsb) +/// ENDFOR +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() +/// \endcode +/// +/// This intrinsic corresponds to the \c TCONJTFP16 instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param a +/// The source tile. Max size is 1024 Bytes. +#define _tile_conjtfp16(dst, a) __builtin_ia32_tconjtfp16((dst), (a)) + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS _tile_tcmmimfp16ps_internal( + unsigned short m, unsigned short n, unsigned short k, _tile1024i dst, + _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_ttcmmimfp16ps_internal(m, n, k, dst, src1, src2); +} + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS _tile_tcmmrlfp16ps_internal( + unsigned short m, unsigned short n, unsigned short k, _tile1024i dst, + _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_ttcmmrlfp16ps_internal(m, n, k, dst, src1, src2); +} + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS _tile_conjtcmmimfp16ps_internal( + unsigned short m, unsigned short n, unsigned short k, _tile1024i dst, + _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_tconjtcmmimfp16ps_internal(m, n, k, dst, src1, src2); +} + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS +_tile_conjtfp16_internal(unsigned short m, unsigned short n, _tile1024i src) { + return __builtin_ia32_tconjtfp16_internal(m, n, src); +} + +/// Perform matrix multiplication of two tiles containing complex elements and +/// accumulate the results into a packed single precision tile. Each dword +/// element in input tiles src0 and src1 is interpreted as a complex number +/// with FP16 real part and FP16 imaginary part. +/// This function calculates the imaginary part of the result. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TTCMMIMFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src0 +/// The 1st source tile. Max size is 1024 Bytes. +/// \param src1 +/// The 2nd source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static void __tile_tcmmimfp16ps(__tile1024i *dst, __tile1024i src0, + __tile1024i src1) { + dst->tile = _tile_tcmmimfp16ps_internal(src0.row, src1.col, src0.col, + dst->tile, src0.tile, src1.tile); +} + +/// Perform matrix multiplication of two tiles containing complex elements and +/// accumulate the results into a packed single precision tile. Each dword +/// element in input tiles src0 and src1 is interpreted as a complex number +/// with FP16 real part and FP16 imaginary part. +/// This function calculates the real part of the result. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TTCMMRLFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src0 +/// The 1st source tile. Max size is 1024 Bytes. +/// \param src1 +/// The 2nd source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static void __tile_tcmmrlfp16ps(__tile1024i *dst, __tile1024i src0, + __tile1024i src1) { + dst->tile = _tile_tcmmrlfp16ps_internal(src0.row, src1.col, src0.col, + dst->tile, src0.tile, src1.tile); +} + +/// Perform matrix conjugate transpose and multiplication of two tiles +/// containing complex elements and accumulate the results into a packed +/// single precision tile. Each dword element in input tiles src0 and src1 +/// is interpreted as a complex number with FP16 real part and FP16 imaginary +/// part. +/// This function calculates the imaginary part of the result. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TCONJTCMMIMFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src0 +/// The 1st source tile. Max size is 1024 Bytes. +/// \param src1 +/// The 2nd source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static void __tile_conjtcmmimfp16ps(__tile1024i *dst, __tile1024i src0, + __tile1024i src1) { + dst->tile = _tile_conjtcmmimfp16ps_internal(src0.row, src1.col, src0.col, + dst->tile, src0.tile, src1.tile); +} + +/// Perform conjugate transpose of an FP16-pair of complex elements from src and +/// writes the result to dst. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TCONJTFP16 instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src +/// The source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static void __tile_conjtfp16(__tile1024i *dst, __tile1024i src) { + dst->tile = _tile_conjtfp16_internal(src.row, src.col, src.tile); +} + +#undef __DEFAULT_FN_ATTRS + +#endif // __x86_64__ +#endif // __AMX_COMPLEXTRANSPOSEINTRIN_H diff --git a/clang/lib/Headers/amxfp16intrin.h b/clang/lib/Headers/amxfp16intrin.h index ed798245d41efbfde190655b0598bc70d1082639..bb4bc31fdafd50dfc144b83740db2d79c0dbdd57 100644 --- a/clang/lib/Headers/amxfp16intrin.h +++ b/clang/lib/Headers/amxfp16intrin.h @@ -15,6 +15,10 @@ #define __AMX_FP16INTRIN_H #ifdef __x86_64__ +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, __target__("amx-fp16"))) + /// Compute dot-product of FP16 (16-bit) floating-point pairs in tiles \a a /// and \a b, accumulating the intermediate single-precision (32-bit) /// floating-point elements with elements in \a dst, and store the 32-bit @@ -54,5 +58,36 @@ #define _tile_dpfp16ps(dst, a, b) \ __builtin_ia32_tdpfp16ps(dst, a, b) +/// This is internal intrinsic. C/C++ user should avoid calling it directly. +static __inline__ _tile1024i __DEFAULT_FN_ATTRS +_tile_dpfp16ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_tdpfp16ps_internal(m, n, k, dst, src1, src2); +} + +/// Compute dot-product of FP16 (16-bit) floating-point pairs in tiles src0 and +/// src1, accumulating the intermediate single-precision (32-bit) floating-point +/// elements with elements in "dst", and store the 32-bit result back to tile +/// "dst". +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TDPFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src0 +/// The 1st source tile. Max size is 1024 Bytes. +/// \param src1 +/// The 2nd source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static __inline__ void __tile_dpfp16ps(__tile1024i *dst, __tile1024i src0, + __tile1024i src1) { + dst->tile = _tile_dpfp16ps_internal(src0.row, src1.col, src0.col, dst->tile, + src0.tile, src1.tile); +} + +#undef __DEFAULT_FN_ATTRS + #endif /* __x86_64__ */ #endif /* __AMX_FP16INTRIN_H */ diff --git a/clang/lib/Headers/amxfp16transposeintrin.h b/clang/lib/Headers/amxfp16transposeintrin.h new file mode 100644 index 0000000000000000000000000000000000000000..191f8c6097a2cc586064a97ddb01c37f5af1aaf8 --- /dev/null +++ b/clang/lib/Headers/amxfp16transposeintrin.h @@ -0,0 +1,94 @@ +/*===----- amxfp16transposeintrin.h - AMX-FP16 and AMX-TRANSPOSE ------------=== + * + * 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 __IMMINTRIN_H +#error \ + "Never use directly; use instead." +#endif /* __IMMINTRIN_H */ + +#ifndef __AMX_FP16TRANSPOSEINTRIN_H +#define __AMX_FP16TRANSPOSEINTRIN_H +#ifdef __x86_64__ + +/* Define the default attributes for the functions in this file. */ +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, \ + __target__("amx-fp16,amx-transpose"))) + +/// Compute transpose and dot-product of FP16 (16-bit) floating-point pairs in +/// tiles \a a and \a b, accumulating the intermediate single-precision +/// (32-bit) floating-point elements with elements in \a dst, and store the +/// 32-bit result back to tile \a dst. +/// +/// \headerfile +/// +/// \code +/// void _tile_tdpfp16ps (__tile dst, __tile a, __tile b) +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// tmp := dst.row[m] +/// FOR k := 0 TO (a.colsb / 4) - 1 +/// FOR n := 0 TO (dst.colsb / 4) - 1 +/// tmp.fp32[n] += FP32(a.row[m].fp16[2*k+0]) * +/// FP32(b.row[k].fp16[2*n+0]) +/// tmp.fp32[n] += FP32(a.row[m].fp16[2*k+1]) * +/// FP32(b.row[k].fp16[2*n+1]) +/// ENDFOR +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// ENDFOR +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() +/// \endcode +/// +/// This intrinsic corresponds to the \c TTDPFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param a +/// The 1st source tile. Max size is 1024 Bytes. +/// \param b +/// The 2nd source tile. Max size is 1024 Bytes. +#define _tile_tdpfp16ps(dst, a, b) __builtin_ia32_ttdpfp16ps((dst), (a), (b)) + +/// This is internal intrinsic. C/C++ user should avoid calling it directly. +static __inline__ _tile1024i __DEFAULT_FN_ATTRS +_tile_tdpfp16ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_ttdpfp16ps_internal(m, n, k, dst, src1, src2); +} + +/// Compute transpose and dot-product of FP16 (16-bit) floating-point pairs in +/// tiles src0 and src1, accumulating the intermediate single-precision +/// (32-bit) floating-point elements with elements in "dst", and store the +/// 32-bit result back to tile "dst". +/// +/// \headerfile +/// +/// This intrinsic corresponds to the TTDPFP16PS instruction. +/// +/// \param dst +/// The destination tile. Max size is 1024 Bytes. +/// \param src0 +/// The 1st source tile. Max size is 1024 Bytes. +/// \param src1 +/// The 2nd source tile. Max size is 1024 Bytes. +__DEFAULT_FN_ATTRS +static __inline__ void __tile_tdpfp16ps(__tile1024i *dst, __tile1024i src0, + __tile1024i src1) { + dst->tile = _tile_tdpfp16ps_internal(src0.row, src1.col, src0.col, dst->tile, + src0.tile, src1.tile); +} + +#undef __DEFAULT_FN_ATTRS + +#endif /* __x86_64__ */ +#endif /* __AMX_FP16TRANSPOSEINTRIN_H */ diff --git a/clang/lib/Headers/amxfp8intrin.h b/clang/lib/Headers/amxfp8intrin.h index 0f5ddc87e5a7525af63b0a226c78107e9c194c96..92e7989974e71a3f26c09200015d99cbb83c2ff7 100644 --- a/clang/lib/Headers/amxfp8intrin.h +++ b/clang/lib/Headers/amxfp8intrin.h @@ -15,81 +15,216 @@ #define __AMXFP8INTRIN_H #ifdef __x86_64__ -/// Peform the dot product of a BF8 value \a a by a BF8 value \a b accumulating -/// into a Single Precision (FP32) source/dest \a dst. +#define __DEFAULT_FN_ATTRS_FP8 \ + __attribute__((__always_inline__, __nodebug__, __target__("amx-fp8"))) + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS_FP8 +_tile_dpbf8ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_tdpbf8ps_internal(m, n, k, dst, src1, src2); +} + +/// Perform the dot product of a BF8 value \a src1 by a BF8 value \a src2 +/// accumulating into a Single Precision (FP32) source/dest \a dst. /// /// \headerfile /// /// \code -/// void _tile_dpbf8ps (__tile dst, __tile a, __tile b) +/// void __tile_dpbf8ps (__tile1024i *dst, __tile1024i src1, __tile1024i src2) +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// temp1[(dst.colsb / 4 - 1) : 0] = 0 +/// FOR k := 0 TO src1.colsb / 4 - 1 +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// temp1[n] += +/// INT64(src1.row[m].float8[4*k+0]) * INT64(src2.row[k].float8[4*n+0]) +/// + INT64(src1.row[m].float8[4*k+1]) * INT64(src2.row[k].float8[4*n+1]) +/// + INT64(src1.row[m].float8[4*k+2]) * INT64(src2.row[k].float8[4*n+2]) +/// + INT64(src1.row[m].float8[4*k+3]) * INT64(src2.row[k].float8[4*n+3]) +/// ENDFOR +/// ENDFOR +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// tmp.row[m].fp32[n] = dst.row[m].fp32[n] + FP32(temp1[n]) +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() /// \endcode /// /// This intrinsic corresponds to the \c TDPBF8PS instruction. /// /// \param dst /// The destination tile. Max size is 1024 Bytes. -/// \param a +/// \param src1 /// The 1st source tile. Max size is 1024 Bytes. -/// \param b +/// \param src2 /// The 2nd source tile. Max size is 1024 Bytes. -#define _tile_dpbf8ps(dst, a, b) __builtin_ia32_tdpbf8ps((dst), (a), (b)) +__DEFAULT_FN_ATTRS_FP8 static void +__tile_dpbf8ps(__tile1024i *dst, __tile1024i src1, __tile1024i src2) { + dst->tile = _tile_dpbf8ps_internal(src1.row, src2.col, src1.col, dst->tile, + src1.tile, src2.tile); +} -/// Perform the dot product of a BF8 value \a a by an HF8 value \a b +static __inline__ _tile1024i __DEFAULT_FN_ATTRS_FP8 +_tile_dpbhf8ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_tdpbhf8ps_internal(m, n, k, dst, src1, src2); +} + +/// Perform the dot product of a BF8 value \a src1 by an HF8 value \a src2 /// accumulating into a Single Precision (FP32) source/dest \a dst. /// /// \headerfile /// /// \code -/// void _tile_dpbhf8ps (__tile dst, __tile a, __tile b) +/// void __tile_dpbhf8ps (__tile1024i dst, __tile1024i src1, __tile1024i src2) +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// temp1[(dst.colsb / 4 - 1) : 0] = 0 +/// FOR k := 0 TO src1.colsb / 4 - 1 +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// temp1[n] += +/// INT64(src1.row[m].float8[4*k+0]) * INT64(src2.row[k].float8[4*n+0]) +/// + INT64(src1.row[m].float8[4*k+1]) * INT64(src2.row[k].float8[4*n+1]) +/// + INT64(src1.row[m].float8[4*k+2]) * INT64(src2.row[k].float8[4*n+2]) +/// + INT64(src1.row[m].float8[4*k+3]) * INT64(src2.row[k].float8[4*n+3]) +/// ENDFOR +/// ENDFOR +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// tmp.row[m].fp32[n] = dst.row[m].fp32[n] + FP32(temp1[n]) +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() /// \endcode /// /// This intrinsic corresponds to the \c TDPBHF8PS instruction. /// /// \param dst /// The destination tile. Max size is 1024 Bytes. -/// \param a +/// \param src1 /// The 1st source tile. Max size is 1024 Bytes. -/// \param b +/// \param src2 /// The 2nd source tile. Max size is 1024 Bytes. -#define _tile_dpbhf8ps(dst, a, b) __builtin_ia32_tdpbhf8ps((dst), (a), (b)) +__DEFAULT_FN_ATTRS_FP8 static void +__tile_dpbhf8ps(__tile1024i *dst, __tile1024i src1, __tile1024i src2) { + dst->tile = _tile_dpbhf8ps_internal(src1.row, src2.col, src1.col, dst->tile, + src1.tile, src2.tile); +} + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS_FP8 +_tile_dphbf8ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_tdphbf8ps_internal(m, n, k, dst, src1, src2); +} -/// Perform the dot product of an HF8 value \a a by a BF8 value \a b +/// Perform the dot product of an HF8 value \a src1 by a BF8 value \a src2 /// accumulating into a Single Precision (FP32) source/dest \a dst. /// /// \headerfile /// /// \code -/// void _tile_dphbf8ps (__tile dst, __tile a, __tile b) +/// void __tile_dphbf8ps (__tile1024i dst, __tile1024i src1, __tile1024i src2) +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// temp1[(dst.colsb / 4 - 1) : 0] = 0 +/// FOR k := 0 TO src1.colsb / 4 - 1 +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// temp1[n] += +/// INT64(src1.row[m].float8[4*k+0]) * INT64(src2.row[k].float8[4*n+0]) +/// + INT64(src1.row[m].float8[4*k+1]) * INT64(src2.row[k].float8[4*n+1]) +/// + INT64(src1.row[m].float8[4*k+2]) * INT64(src2.row[k].float8[4*n+2]) +/// + INT64(src1.row[m].float8[4*k+3]) * INT64(src2.row[k].float8[4*n+3]) +/// ENDFOR +/// ENDFOR +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// tmp.row[m].fp32[n] = dst.row[m].fp32[n] + FP32(temp1[n]) +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() /// \endcode /// /// This intrinsic corresponds to the \c TDPHBF8PS instruction. /// /// \param dst /// The destination tile. Max size is 1024 Bytes. -/// \param a +/// \param src1 /// The 1st source tile. Max size is 1024 Bytes. -/// \param b +/// \param src2 /// The 2nd source tile. Max size is 1024 Bytes. -#define _tile_dphbf8ps(dst, a, b) __builtin_ia32_tdphbf8ps((dst), (a), (b)) -/// Perform the dot product of an HF8 value \a a by an HF8 value \a b +__DEFAULT_FN_ATTRS_FP8 static void +__tile_dphbf8ps(__tile1024i *dst, __tile1024i src1, __tile1024i src2) { + dst->tile = _tile_dphbf8ps_internal(src1.row, src2.col, src1.col, dst->tile, + src1.tile, src2.tile); +} + +static __inline__ _tile1024i __DEFAULT_FN_ATTRS_FP8 +_tile_dphf8ps_internal(unsigned short m, unsigned short n, unsigned short k, + _tile1024i dst, _tile1024i src1, _tile1024i src2) { + return __builtin_ia32_tdphf8ps_internal(m, n, k, dst, src1, src2); +} + +/// Perform the dot product of an HF8 value \a src1 by an HF8 value \a src2 /// accumulating into a Single Precision (FP32) source/dest \a dst. /// /// \headerfile /// /// \code -/// void _tile_dphf8ps (__tile dst, __tile a, __tile b) +/// void __tile_dphf8ps (__tile1024i dst, __tile1024i src1, __tile1024i src2) +/// \endcode +/// +/// \code{.operation} +/// FOR m := 0 TO dst.rows - 1 +/// temp1[(dst.colsb / 4 - 1) : 0] = 0 +/// FOR k := 0 TO src1.colsb / 4 - 1 +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// temp1[n] += +/// INT64(src1.row[m].float8[4*k+0]) * INT64(src2.row[k].float8[4*n+0]) +/// + INT64(src1.row[m].float8[4*k+1]) * INT64(src2.row[k].float8[4*n+1]) +/// + INT64(src1.row[m].float8[4*k+2]) * INT64(src2.row[k].float8[4*n+2]) +/// + INT64(src1.row[m].float8[4*k+3]) * INT64(src2.row[k].float8[4*n+3]) +/// ENDFOR +/// ENDFOR +/// FOR n := 0 TO dst.colsb / 4 - 1 +/// tmp.row[m].fp32[n] = dst.row[m].fp32[n] + FP32(temp1[n]) +/// ENDFOR +/// write_row_and_zero(dst, m, tmp, dst.colsb) +/// zero_upper_rows(dst, dst.rows) +/// zero_tileconfig_start() /// \endcode /// /// This intrinsic corresponds to the \c TDPHF8PS instruction. /// /// \param dst /// The destination tile. Max size is 1024 Bytes. -/// \param a +/// \param src1 /// The 1st source tile. Max size is 1024 Bytes. -/// \param b +/// \param src2 /// The 2nd source tile. Max size is 1024 Bytes. -#define _tile_dphf8ps(dst, a, b) __builtin_ia32_tdphf8ps((dst), (a), (b)) +__DEFAULT_FN_ATTRS_FP8 static void +__tile_dphf8ps(__tile1024i *dst, __tile1024i src1, __tile1024i src2) { + dst->tile = _tile_dphf8ps_internal(src1.row, src2.col, src1.col, dst->tile, + src1.tile, src2.tile); +} + +#define _tile_dpbf8ps(dst, src1, src2) \ + __builtin_ia32_tdpbf8ps((dst), (src1), (src2)) +#define _tile_dpbhf8ps(dst, src1, src2) \ + __builtin_ia32_tdpbhf8ps((dst), (src1), (src2)) +#define _tile_dphbf8ps(dst, src1, src2) \ + __builtin_ia32_tdphbf8ps((dst), (src1), (src2)) +#define _tile_dphf8ps(dst, src1, src2) \ + __builtin_ia32_tdphf8ps((dst), (src1), (src2)) + +#undef __DEFAULT_FN_ATTRS_FP8 #endif /* __x86_64__ */ #endif /* __AMXFP8INTRIN_H */ diff --git a/clang/lib/Headers/amxintrin.h b/clang/lib/Headers/amxintrin.h index f07a56890118537f284a55576ca14e1fa99b4484..b0140615677f277c30bf07747929878743891e41 100644 --- a/clang/lib/Headers/amxintrin.h +++ b/clang/lib/Headers/amxintrin.h @@ -22,8 +22,6 @@ __attribute__((__always_inline__, __nodebug__, __target__("amx-int8"))) #define __DEFAULT_FN_ATTRS_BF16 \ __attribute__((__always_inline__, __nodebug__, __target__("amx-bf16"))) -#define __DEFAULT_FN_ATTRS_FP16 \ - __attribute__((__always_inline__, __nodebug__, __target__("amx-fp16"))) /// Load tile configuration from a 64-byte memory location specified by /// "mem_addr". The tile configuration includes the tile type palette, the @@ -294,13 +292,6 @@ _tile_dpbf16ps_internal(unsigned short m, unsigned short n, unsigned short k, return __builtin_ia32_tdpbf16ps_internal(m, n, k, dst, src1, src2); } -/// This is internal intrinsic. C/C++ user should avoid calling it directly. -static __inline__ _tile1024i __DEFAULT_FN_ATTRS_FP16 -_tile_dpfp16ps_internal(unsigned short m, unsigned short n, unsigned short k, - _tile1024i dst, _tile1024i src1, _tile1024i src2) { - return __builtin_ia32_tdpfp16ps_internal(m, n, k, dst, src1, src2); -} - /// This struct pack the shape and tile data together for user. We suggest /// initializing the struct as early as possible, because compiler depends /// on the shape information to do configure. The constant value is preferred @@ -495,32 +486,9 @@ static __inline__ void __tile_dpbf16ps(__tile1024i *dst, __tile1024i src0, src0.tile, src1.tile); } -/// Compute dot-product of FP16 (16-bit) floating-point pairs in tiles src0 and -/// src1, accumulating the intermediate single-precision (32-bit) floating-point -/// elements with elements in "dst", and store the 32-bit result back to tile -/// "dst". -/// -/// \headerfile -/// -/// This intrinsic corresponds to the TDPFP16PS instruction. -/// -/// \param dst -/// The destination tile. Max size is 1024 Bytes. -/// \param src0 -/// The 1st source tile. Max size is 1024 Bytes. -/// \param src1 -/// The 2nd source tile. Max size is 1024 Bytes. -__DEFAULT_FN_ATTRS_FP16 -static __inline__ void __tile_dpfp16ps(__tile1024i *dst, __tile1024i src0, - __tile1024i src1) { - dst->tile = _tile_dpfp16ps_internal(src0.row, src1.col, src0.col, dst->tile, - src0.tile, src1.tile); -} - #undef __DEFAULT_FN_ATTRS_TILE #undef __DEFAULT_FN_ATTRS_INT8 #undef __DEFAULT_FN_ATTRS_BF16 -#undef __DEFAULT_FN_ATTRS_FP16 #endif /* __x86_64__ */ #endif /* __AMXINTRIN_H */ diff --git a/clang/lib/Headers/cuda_wrappers/new b/clang/lib/Headers/cuda_wrappers/new index d5fb3b7011de9685a3c98aa8e186c4508f7fac69..9d3e31690e677c3c13372c9d1fa7218d89699e00 100644 --- a/clang/lib/Headers/cuda_wrappers/new +++ b/clang/lib/Headers/cuda_wrappers/new @@ -91,12 +91,14 @@ __device__ inline void operator delete[](void *ptr, #endif // Device overrides for placement new and delete. +#if !(_LIBCPP_STD_VER >= 26 || __cpp_lib_constexpr_new >= 202406L) __device__ inline void *operator new(__SIZE_TYPE__, void *__ptr) CUDA_NOEXCEPT { return __ptr; } __device__ inline void *operator new[](__SIZE_TYPE__, void *__ptr) CUDA_NOEXCEPT { return __ptr; } +#endif __device__ inline void operator delete(void *, void *) CUDA_NOEXCEPT {} __device__ inline void operator delete[](void *, void *) CUDA_NOEXCEPT {} diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 2ee3827d7204957cbdc64597b62def69421ac8aa..f84f48fc1c122d43d76b366a214ca445ee3260b6 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -655,6 +655,23 @@ double3 clamp(double3, double3, double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) double4 clamp(double4, double4, double4); +//===----------------------------------------------------------------------===// +// clip builtins +//===----------------------------------------------------------------------===// + +/// \fn void clip(T Val) +/// \brief Discards the current pixel if the specified value is less than zero. +/// \param Val The input value. + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clip) +void clip(float4); + //===----------------------------------------------------------------------===// // cos builtins //===----------------------------------------------------------------------===// diff --git a/clang/lib/Headers/immintrin.h b/clang/lib/Headers/immintrin.h index f0dd7160ec7ff450e0050708a1da75c6ca033ae3..19c5987257a27e4cbab6023023ab47fc3fdbf0dc 100644 --- a/clang/lib/Headers/immintrin.h +++ b/clang/lib/Headers/immintrin.h @@ -605,6 +605,10 @@ _storebe_i64(void * __P, long long __D) { #include #endif +#if !defined(__SCE__) || __has_feature(modules) || defined(__MOVRS__) +#include +#endif + #if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX10_2__) && defined(__MOVRS__)) #include @@ -630,9 +634,6 @@ _storebe_i64(void * __P, long long __D) { #if !defined(__SCE__) || __has_feature(modules) || defined(__INVPCID__) #include #endif -#if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_FP16__) -#include -#endif #if !defined(__SCE__) || __has_feature(modules) || defined(__KL__) || \ defined(__WIDEKL__) @@ -644,6 +645,10 @@ _storebe_i64(void * __P, long long __D) { #include #endif +#if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_FP16__) +#include +#endif + #if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_COMPLEX__) #include #endif @@ -678,6 +683,21 @@ _storebe_i64(void * __P, long long __D) { #include #endif +#if !defined(__SCE__) || __has_feature(modules) || \ + (defined(__AMX_BF16__) && defined(__AMX_TRANSPOSE__)) +#include +#endif + +#if !defined(__SCE__) || __has_feature(modules) || \ + (defined(__AMX_FP16__) && defined(__AMX_TRANSPOSE__)) +#include +#endif + +#if !defined(__SCE__) || __has_feature(modules) || \ + (defined(__AMX_COMPLEX__) && defined(__AMX_TRANSPOSE__)) +#include +#endif + #if !defined(__SCE__) || __has_feature(modules) || \ defined(__AVX512VP2INTERSECT__) #include diff --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h index f4218295919a0d0d633e6a7b2f1bb81f83c96eda..a1247d12e21f8fe3bda852287671a0d7abed6f7f 100644 --- a/clang/lib/Headers/larchintrin.h +++ b/clang/lib/Headers/larchintrin.h @@ -228,17 +228,31 @@ extern __inline void ((void)__builtin_loongarch_ldpte_d((long int)(_1), (_2))) #endif -#define __frecipe_s(/*float*/ _1) \ - (float)__builtin_loongarch_frecipe_s((float)_1) +#ifdef __loongarch_frecipe +extern __inline float + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __frecipe_s(float _1) { + return __builtin_loongarch_frecipe_s(_1); +} -#define __frecipe_d(/*double*/ _1) \ - (double)__builtin_loongarch_frecipe_d((double)_1) +extern __inline double + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __frecipe_d(double _1) { + return __builtin_loongarch_frecipe_d(_1); +} -#define __frsqrte_s(/*float*/ _1) \ - (float)__builtin_loongarch_frsqrte_s((float)_1) +extern __inline float + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __frsqrte_s(float _1) { + return __builtin_loongarch_frsqrte_s(_1); +} -#define __frsqrte_d(/*double*/ _1) \ - (double)__builtin_loongarch_frsqrte_d((double)_1) +extern __inline double + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) + __frsqrte_d(double _1) { + return __builtin_loongarch_frsqrte_d(_1); +} +#endif #ifdef __cplusplus } diff --git a/clang/lib/Headers/lasxintrin.h b/clang/lib/Headers/lasxintrin.h index dafc2a2f3e6a70bd1aa46b2f7998ee3f223fc55c..85020d82829e2af135cfcffc748fc20e6a529748 100644 --- a/clang/lib/Headers/lasxintrin.h +++ b/clang/lib/Headers/lasxintrin.h @@ -1726,18 +1726,6 @@ extern __inline return (__m256d)__builtin_lasx_xvfrecip_d((v4f64)_1); } -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256 - __lasx_xvfrecipe_s(__m256 _1) { - return (__m256)__builtin_lasx_xvfrecipe_s((v8f32)_1); -} - -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256d - __lasx_xvfrecipe_d(__m256d _1) { - return (__m256d)__builtin_lasx_xvfrecipe_d((v4f64)_1); -} - extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256 __lasx_xvfrint_s(__m256 _1) { @@ -1762,18 +1750,6 @@ extern __inline return (__m256d)__builtin_lasx_xvfrsqrt_d((v4f64)_1); } -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256 - __lasx_xvfrsqrte_s(__m256 _1) { - return (__m256)__builtin_lasx_xvfrsqrte_s((v8f32)_1); -} - -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256d - __lasx_xvfrsqrte_d(__m256d _1) { - return (__m256d)__builtin_lasx_xvfrsqrte_d((v4f64)_1); -} - extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256 __lasx_xvflogb_s(__m256 _1) { @@ -2585,7 +2561,7 @@ extern __inline extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256i __lasx_xvorn_v(__m256i _1, __m256i _2) { - return (__m256i)__builtin_lasx_xvorn_v((v32i8)_1, (v32i8)_2); + return (__m256i)__builtin_lasx_xvorn_v((v32u8)_1, (v32u8)_2); } #define __lasx_xvldi(/*i13*/ _1) ((__m256i)__builtin_lasx_xvldi((_1))) @@ -3866,6 +3842,32 @@ extern __inline return (__m256i)__builtin_lasx_xvfcmp_sun_s((v8f32)_1, (v8f32)_2); } +#if defined(__loongarch_frecipe) +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256 + __lasx_xvfrecipe_s(__m256 _1) { + return (__m256)__builtin_lasx_xvfrecipe_s((v8f32)_1); +} + +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256d + __lasx_xvfrecipe_d(__m256d _1) { + return (__m256d)__builtin_lasx_xvfrecipe_d((v4f64)_1); +} + +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256 + __lasx_xvfrsqrte_s(__m256 _1) { + return (__m256)__builtin_lasx_xvfrsqrte_s((v8f32)_1); +} + +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256d + __lasx_xvfrsqrte_d(__m256d _1) { + return (__m256d)__builtin_lasx_xvfrsqrte_d((v4f64)_1); +} +#endif + #define __lasx_xvpickve_d_f(/*__m256d*/ _1, /*ui2*/ _2) \ ((__m256d)__builtin_lasx_xvpickve_d_f((v4f64)(_1), (_2))) diff --git a/clang/lib/Headers/limits.h b/clang/lib/Headers/limits.h index 56dffe568486cc597243d11184321fcbb86230f1..d08227fe4d3d487f829f969f643f4488833d079d 100644 --- a/clang/lib/Headers/limits.h +++ b/clang/lib/Headers/limits.h @@ -111,11 +111,14 @@ #define ULLONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL) #endif -/* LONG_LONG_MIN/LONG_LONG_MAX/ULONG_LONG_MAX are a GNU extension. It's too bad - that we don't have something like #pragma poison that could be used to - deprecate a macro - the code should just use LLONG_MAX and friends. +/* LONG_LONG_MIN/LONG_LONG_MAX/ULONG_LONG_MAX are a GNU extension. Android's + bionic also defines them. It's too bad that we don't have something like + #pragma poison that could be used to deprecate a macro - the code should just + use LLONG_MAX and friends. */ -#if defined(__GNU_LIBRARY__) ? defined(__USE_GNU) : !defined(__STRICT_ANSI__) +#if (defined(__GNU_LIBRARY__) ? defined(__USE_GNU) \ + : !defined(__STRICT_ANSI__)) || \ + defined(__BIONIC__) #undef LONG_LONG_MIN #undef LONG_LONG_MAX diff --git a/clang/lib/Headers/lsxintrin.h b/clang/lib/Headers/lsxintrin.h index f347955ce6fb51303a8a70f28e229c9a8b00aec7..a9b19223fc4be843e8376eaf6211076c1525c132 100644 --- a/clang/lib/Headers/lsxintrin.h +++ b/clang/lib/Headers/lsxintrin.h @@ -1776,18 +1776,6 @@ extern __inline return (__m128d)__builtin_lsx_vfrecip_d((v2f64)_1); } -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128 - __lsx_vfrecipe_s(__m128 _1) { - return (__m128)__builtin_lsx_vfrecipe_s((v4f32)_1); -} - -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128d - __lsx_vfrecipe_d(__m128d _1) { - return (__m128d)__builtin_lsx_vfrecipe_d((v2f64)_1); -} - extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128 __lsx_vfrint_s(__m128 _1) { @@ -1812,18 +1800,6 @@ extern __inline return (__m128d)__builtin_lsx_vfrsqrt_d((v2f64)_1); } -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128 - __lsx_vfrsqrte_s(__m128 _1) { - return (__m128)__builtin_lsx_vfrsqrte_s((v4f32)_1); -} - -extern __inline - __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128d - __lsx_vfrsqrte_d(__m128d _1) { - return (__m128d)__builtin_lsx_vfrsqrte_d((v2f64)_1); -} - extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128 __lsx_vflogb_s(__m128 _1) { @@ -3425,7 +3401,7 @@ extern __inline extern __inline __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128i __lsx_vorn_v(__m128i _1, __m128i _2) { - return (__m128i)__builtin_lsx_vorn_v((v16i8)_1, (v16i8)_2); + return (__m128i)__builtin_lsx_vorn_v((v16u8)_1, (v16u8)_2); } #define __lsx_vldi(/*i13*/ _1) ((__m128i)__builtin_lsx_vldi((_1))) @@ -3738,6 +3714,32 @@ extern __inline return (__m128i)__builtin_lsx_vfcmp_sun_s((v4f32)_1, (v4f32)_2); } +#if defined(__loongarch_frecipe) +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128 + __lsx_vfrecipe_s(__m128 _1) { + return (__m128)__builtin_lsx_vfrecipe_s((v4f32)_1); +} + +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128d + __lsx_vfrecipe_d(__m128d _1) { + return (__m128d)__builtin_lsx_vfrecipe_d((v2f64)_1); +} + +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128 + __lsx_vfrsqrte_s(__m128 _1) { + return (__m128)__builtin_lsx_vfrsqrte_s((v4f32)_1); +} + +extern __inline + __attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128d + __lsx_vfrsqrte_d(__m128d _1) { + return (__m128d)__builtin_lsx_vfrsqrte_d((v2f64)_1); +} +#endif + #define __lsx_vrepli_b(/*si10*/ _1) ((__m128i)__builtin_lsx_vrepli_b((_1))) #define __lsx_vrepli_d(/*si10*/ _1) ((__m128i)__builtin_lsx_vrepli_d((_1))) diff --git a/clang/lib/Headers/movrsintrin.h b/clang/lib/Headers/movrsintrin.h new file mode 100644 index 0000000000000000000000000000000000000000..250f4004cd2b7aaf88f7f956b6eec6fc0def590c --- /dev/null +++ b/clang/lib/Headers/movrsintrin.h @@ -0,0 +1,59 @@ +/*===---------------- movrsintrin.h - MOVRS intrinsics ----------------------=== + * + * 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 __IMMINTRIN_H +#error "Never use directly; include instead." +#endif // __IMMINTRIN_H + +#ifndef __MOVRSINTRIN_H +#define __MOVRSINTRIN_H + +#define __DEFAULT_FN_ATTRS \ + __attribute__((__always_inline__, __nodebug__, __target__("movrs"))) + +#ifdef __x86_64__ +static __inline__ char __DEFAULT_FN_ATTRS _movrs_i8(const void *__A) { + return (char)__builtin_ia32_movrsqi((const void *)__A); +} + +static __inline__ short __DEFAULT_FN_ATTRS _movrs_i16(const void *__A) { + return (short)__builtin_ia32_movrshi((const void *)__A); +} + +static __inline__ int __DEFAULT_FN_ATTRS _movrs_i32(const void *__A) { + return (int)__builtin_ia32_movrssi((const void *)__A); +} + +static __inline__ long long __DEFAULT_FN_ATTRS _movrs_i64(const void *__A) { + return (long long)__builtin_ia32_movrsdi((const void *)__A); +} +#endif // __x86_64__ + +// Loads a memory sequence containing the specified memory address into +/// the L3 data cache. Data will be shared (read/written) to by requesting +/// core and other cores. +/// +/// Note that the effect of this intrinsic is dependent on the processor +/// implementation. +/// +/// \headerfile +/// +/// This intrinsic corresponds to the \c PREFETCHRS instruction. +/// +/// \param __P +/// A pointer specifying the memory address to be prefetched. +static __inline__ void __DEFAULT_FN_ATTRS +_m_prefetchrs(volatile const void *__P) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-qual" + __builtin_ia32_prefetchrs((const void *)__P); +#pragma clang diagnostic pop +} + +#undef __DEFAULT_FN_ATTRS +#endif // __MOVRSINTRIN_H \ No newline at end of file diff --git a/clang/lib/Headers/nvptxintrin.h b/clang/lib/Headers/nvptxintrin.h index 8b68b807cac4f3196e9c40780e1444bbef4ee673..962dca9cf03126f27d247e80106b815afc13c34d 100644 --- a/clang/lib/Headers/nvptxintrin.h +++ b/clang/lib/Headers/nvptxintrin.h @@ -24,11 +24,11 @@ _Pragma("omp begin declare target device_type(nohost)"); _Pragma("omp begin declare variant match(device = {arch(nvptx64)})"); // Type aliases to the address spaces used by the NVPTX backend. -#define __gpu_private __attribute__((opencl_private)) -#define __gpu_constant __attribute__((opencl_constant)) -#define __gpu_local __attribute__((opencl_local)) -#define __gpu_global __attribute__((opencl_global)) -#define __gpu_generic __attribute__((opencl_generic)) +#define __gpu_private __attribute__((address_space(5))) +#define __gpu_constant __attribute__((address_space(4))) +#define __gpu_local __attribute__((address_space(3))) +#define __gpu_global __attribute__((address_space(1))) +#define __gpu_generic __attribute__((address_space(0))) // Attribute to declare a function as a kernel. #define __gpu_kernel __attribute__((nvptx_kernel, visibility("protected"))) diff --git a/clang/lib/InstallAPI/DirectoryScanner.cpp b/clang/lib/InstallAPI/DirectoryScanner.cpp index 03a8208c7364e91f4cd757cfd27edd0d117a118b..be43a96f3d97d17044288c105bf714256aa92aa0 100644 --- a/clang/lib/InstallAPI/DirectoryScanner.cpp +++ b/clang/lib/InstallAPI/DirectoryScanner.cpp @@ -277,7 +277,8 @@ llvm::Error DirectoryScanner::scanForFrameworks(StringRef Directory) { // Expect a certain directory structure and naming convention to find // frameworks. static const char *SubDirectories[] = {"System/Library/Frameworks/", - "System/Library/PrivateFrameworks/"}; + "System/Library/PrivateFrameworks/", + "System/Library/SubFrameworks"}; // Check if the directory is already a framework. if (isFramework(Directory)) { diff --git a/clang/lib/Interpreter/CMakeLists.txt b/clang/lib/Interpreter/CMakeLists.txt index d5ffe78251d253865a2d4854eee9e65cfa13bc3c..df7ea82e0dada54d52d23ffc7dde04d017d0b637 100644 --- a/clang/lib/Interpreter/CMakeLists.txt +++ b/clang/lib/Interpreter/CMakeLists.txt @@ -10,7 +10,8 @@ set(LLVM_LINK_COMPONENTS Support Target TargetParser - ) + TransformUtils + ) if (EMSCRIPTEN AND "lld" IN_LIST LLVM_ENABLE_PROJECTS) set(WASM_SRC Wasm.cpp) diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index 7954cde36588bda4082e6cd7b4d0c5a98fd2b517..dbd61f0b8b1ebb7d0ec053011795e89e7dd955e7 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -56,7 +56,7 @@ public: virtual llvm::Error addModule(PartialTranslationUnit &PTU); virtual llvm::Error removeModule(PartialTranslationUnit &PTU); virtual llvm::Error runCtors() const; - llvm::Error cleanUp(); + virtual llvm::Error cleanUp(); llvm::Expected getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const; diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index bc96da811d44cbe3d1b57520a36e684ac0671365..5dc67f6375098f44d793920911b72a714c169428 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -15,6 +15,7 @@ #include "IncrementalExecutor.h" #include "IncrementalParser.h" #include "InterpreterUtils.h" +#include "llvm/Support/VirtualFileSystem.h" #ifdef __EMSCRIPTEN__ #include "Wasm.h" #endif // __EMSCRIPTEN__ @@ -50,6 +51,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" +#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule + +#define DEBUG_TYPE "clang-repl" using namespace clang; // FIXME: Figure out how to unify with namespace init_convenience from @@ -103,7 +107,7 @@ CreateCI(const llvm::opt::ArgStringList &Argv) { CompilerInvocation::GetResourcesPath(Argv[0], nullptr); // Create the actual diagnostics engine. - Clang->createDiagnostics(); + Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); if (!Clang->hasDiagnostics()) return llvm::createStringError(llvm::errc::not_supported, "Initialization failed. " @@ -196,7 +200,6 @@ IncrementalCompilerBuilder::CreateCpp() { #ifdef __EMSCRIPTEN__ Argv.push_back("-target"); Argv.push_back("wasm32-unknown-emscripten"); - Argv.push_back("-pie"); Argv.push_back("-shared"); #endif Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end()); @@ -339,19 +342,8 @@ public: } void ExecuteAction() override { - CompilerInstance &CI = getCompilerInstance(); - assert(CI.hasPreprocessor() && "No PP!"); - - // Use a code completion consumer? - CodeCompleteConsumer *CompletionConsumer = nullptr; - if (CI.hasCodeCompletionConsumer()) - CompletionConsumer = &CI.getCodeCompletionConsumer(); - - Preprocessor &PP = CI.getPreprocessor(); - PP.EnterMainSourceFile(); - - if (!CI.hasSema()) - CI.createSema(getTranslationUnitKind(), CompletionConsumer); + WrapperFrontendAction::ExecuteAction(); + getCompilerInstance().getSema().CurContext = nullptr; } // Do not terminate after processing the input. This allows us to keep various @@ -385,8 +377,6 @@ Interpreter::Interpreter(std::unique_ptr Instance, return; CI->ExecuteAction(*Act); - ASTContext &C = CI->getASTContext(); - IncrParser = std::make_unique(*CI, ErrOut); if (ErrOut) @@ -394,18 +384,22 @@ Interpreter::Interpreter(std::unique_ptr Instance, if (getCodeGen()) { CachedInCodeGenModule = GenModule(); + // The initial PTU is filled by `-include` or by CUDA includes + // automatically. + if (!CI->getPreprocessorOpts().Includes.empty()) { + // We can't really directly pass the CachedInCodeGenModule to the Jit + // because it will steal it, causing dangling references as explained in + // Interpreter::Execute + auto M = llvm::CloneModule(*CachedInCodeGenModule); + ASTContext &C = CI->getASTContext(); + RegisterPTU(C.getTranslationUnitDecl(), std::move(M)); + } if (llvm::Error Err = CreateExecutor()) { ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); return; } } - // The initial PTU is filled by `-include` or by CUDA includes automatically. - RegisterPTU(C.getTranslationUnitDecl()); - - // Prepare the IncrParser for input. - llvm::cantFail(Parse("")); - // Not all frontends support code-generation, e.g. ast-dump actions don't if (getCodeGen()) { // Process the PTUs that came from initialization. For example -include will @@ -535,14 +529,25 @@ size_t Interpreter::getEffectivePTUSize() const { return PTUs.size() - InitPTUSize; } -PartialTranslationUnit &Interpreter::RegisterPTU(TranslationUnitDecl *TU) { +PartialTranslationUnit & +Interpreter::RegisterPTU(TranslationUnitDecl *TU, + std::unique_ptr M /*={}*/) { PTUs.emplace_back(PartialTranslationUnit()); PartialTranslationUnit &LastPTU = PTUs.back(); LastPTU.TUPart = TU; - if (std::unique_ptr M = GenModule()) - LastPTU.TheModule = std::move(M); + if (!M) + M = GenModule(); + + assert((!getCodeGen() || M) && "Must have a llvm::Module at this point"); + LastPTU.TheModule = std::move(M); + LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1 + << ": [TU=" << LastPTU.TUPart); + if (LastPTU.TheModule) + LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " (" + << LastPTU.TheModule->getName() << ")"); + LLVM_DEBUG(llvm::dbgs() << "]\n"); return LastPTU; } @@ -615,6 +620,14 @@ void Interpreter::ResetExecutor() { IncrExecutor.reset(); } llvm::Error Interpreter::Execute(PartialTranslationUnit &T) { assert(T.TheModule); + LLVM_DEBUG(llvm::dbgs() + << "execute-ptu " + << ((std::find(PTUs.begin(), PTUs.end(), T) != PTUs.end()) + ? std::distance(PTUs.begin(), + std::find(PTUs.begin(), PTUs.end(), T)) + : -1) + << ": [TU=" << T.TUPart << ", M=" << T.TheModule.get() << " (" + << T.TheModule->getName() << ")]\n"); if (!IncrExecutor) { auto Err = CreateExecutor(); if (Err) @@ -723,10 +736,12 @@ std::unique_ptr Interpreter::GenModule() { // of the module which does not map well to CodeGen's design. To work this // around we created an empty module to make CodeGen happy. We should make // sure it always stays empty. - assert((!CachedInCodeGenModule || (CachedInCodeGenModule->empty() && - CachedInCodeGenModule->global_empty() && - CachedInCodeGenModule->alias_empty() && - CachedInCodeGenModule->ifunc_empty())) && + assert(((!CachedInCodeGenModule || + !getCompilerInstance()->getPreprocessorOpts().Includes.empty()) || + (CachedInCodeGenModule->empty() && + CachedInCodeGenModule->global_empty() && + CachedInCodeGenModule->alias_empty() && + CachedInCodeGenModule->ifunc_empty())) && "CodeGen wrote to a readonly module"); std::unique_ptr M(CG->ReleaseModule()); CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext()); diff --git a/clang/lib/Interpreter/Wasm.cpp b/clang/lib/Interpreter/Wasm.cpp index 1001410aa0f279c72826a4c24a9954cb1f7a091b..79efbaa03982d01a53a6a77a77b2caae2a52e753 100644 --- a/clang/lib/Interpreter/Wasm.cpp +++ b/clang/lib/Interpreter/Wasm.cpp @@ -72,13 +72,13 @@ llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) { OutputFile.close(); std::vector LinkerArgs = {"wasm-ld", - "-pie", + "-shared", "--import-memory", "--no-entry", "--export-all", "--experimental-pic", - "--no-export-dynamic", "--stack-first", + "--allow-undefined", OutputFileName.c_str(), "-o", OutputFileName.c_str()}; @@ -109,6 +109,12 @@ llvm::Error WasmIncrementalExecutor::runCtors() const { return llvm::Error::success(); } +llvm::Error WasmIncrementalExecutor::cleanUp() const { + // Can't call cleanUp through IncrementalExecutor as it + // tries to deinitialize JIT which hasn't been initialized + return llvm::Error::success(); +} + WasmIncrementalExecutor::~WasmIncrementalExecutor() = default; } // namespace clang diff --git a/clang/lib/Interpreter/Wasm.h b/clang/lib/Interpreter/Wasm.h index b1fd88024f14d7cc2650d7f54d93b8d050d1115a..4632613326d39ba6bcd63639ae8e9e87b4032e41 100644 --- a/clang/lib/Interpreter/Wasm.h +++ b/clang/lib/Interpreter/Wasm.h @@ -28,6 +28,7 @@ public: llvm::Error addModule(PartialTranslationUnit &PTU) override; llvm::Error removeModule(PartialTranslationUnit &PTU) override; llvm::Error runCtors() const override; + llvm::Error cleanUp() override; ~WasmIncrementalExecutor() override; }; diff --git a/clang/lib/Lex/HeaderMap.cpp b/clang/lib/Lex/HeaderMap.cpp index b04f67a4b2ed3ce347080cd5b8b7c6c0edb7ed2f..14731f29486c8cb1eae1c689e53a852a73afe511 100644 --- a/clang/lib/Lex/HeaderMap.cpp +++ b/clang/lib/Lex/HeaderMap.cpp @@ -14,13 +14,10 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "clang/Lex/HeaderMapTypes.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/SystemZ/zOSSupport.h" #include #include diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index c5614a8e0ee526d35252f95dd01c2d79893a706e..bf8fe44e4ca9ca45cee72caf6e9237be1dfc30cd 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -24,7 +24,6 @@ #include "clang/Lex/ModuleMap.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp index 86c2ecdf9e36eb4999bb2151035e63e6ba91aec6..ea02f5dfb62644d6ccb4b9cbb7bea08ffda8c4d6 100644 --- a/clang/lib/Lex/InitHeaderSearch.cpp +++ b/clang/lib/Lex/InitHeaderSearch.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/DiagnosticFrontend.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Config/config.h" // C_INCLUDE_DIRS @@ -18,8 +17,6 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" @@ -346,6 +343,7 @@ void InitHeaderSearch::AddDefaultIncludePaths( AddPath("/System/DriverKit/System/Library/Frameworks", System, true); } else { AddPath("/System/Library/Frameworks", System, true); + AddPath("/System/Library/SubFrameworks", System, true); AddPath("/Library/Frameworks", System, true); } } diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 12cb46042c946b5264082219d65e87de5bbace45..e58c8bc72ae5b37e612fb889edc390923b6b6204 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -32,7 +32,6 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/NativeFormatting.h" #include "llvm/Support/Unicode.h" diff --git a/clang/lib/Lex/MacroArgs.cpp b/clang/lib/Lex/MacroArgs.cpp index c54f69bb9ead39125429d9d01c884b5e1160e164..2f97d9e02bc1171b4c98386856442e86420cb99b 100644 --- a/clang/lib/Lex/MacroArgs.cpp +++ b/clang/lib/Lex/MacroArgs.cpp @@ -14,7 +14,6 @@ #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/SaveAndRestore.h" #include diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp index dfdf463665f3c137aa6e1ec1c931f009620dc005..c33276ea71cb7a561fa6cb86fba7b52c1c04a486 100644 --- a/clang/lib/Lex/MacroInfo.cpp +++ b/clang/lib/Lex/MacroInfo.cpp @@ -18,8 +18,6 @@ #include "clang/Basic/TokenKinds.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/Token.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index dc9d2bfd5629c95351db7ddf93e9b0bd61640516..ccf94f6345ff280079f391eab26e9eeb2c9b7d6c 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -30,7 +30,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -38,7 +37,6 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" diff --git a/clang/lib/Lex/PPCallbacks.cpp b/clang/lib/Lex/PPCallbacks.cpp index f2b60a728e90178fcf135a7416d835e31c4f7ebc..cf473aa4df6564e3a1191dd9457fc2daae11a3c9 100644 --- a/clang/lib/Lex/PPCallbacks.cpp +++ b/clang/lib/Lex/PPCallbacks.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "clang/Lex/PPCallbacks.h" -#include "clang/Basic/FileManager.h" using namespace clang; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 8e7d80aa8911c83ce731550ab229ab591526a88e..a23ad40884f249a5ca2f01f4bfc03d328b5f61ee 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -23,7 +23,6 @@ #include "clang/Basic/TokenKinds.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" @@ -38,19 +37,16 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" #include #include #include -#include #include #include #include diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp index 8bb82bd22eb98f56c409fe493070a4adab2b079e..a3b1384f0fa1d6a95d0f274d9c7bc8964ea6c88c 100644 --- a/clang/lib/Lex/PPExpressions.cpp +++ b/clang/lib/Lex/PPExpressions.cpp @@ -29,7 +29,6 @@ #include "clang/Lex/Token.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 1a71f03b1823674ad7869ef9ba2b64ac82e10fc7..22d7c4e0132732e58ac750f338e0b019790bdcf2 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -19,7 +19,6 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/Path.h" #include diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index b757e20f71ffca0c0c5f8347b43d7c9390d48d7b..347c13da0ad215ae184a6928d6b4ca5a15b6b5a0 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -14,11 +14,9 @@ #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/CodeCompletionHandler.h" @@ -38,11 +36,9 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index 6ec63b91df4bec4ee1600782ad6673a03e8c1552..e339ca8422278446aba3a139a2c9ba94ae77acf3 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -14,7 +14,6 @@ #include "clang/Lex/Pragma.h" #include "clang/Basic/CLWarnings.h" #include "clang/Basic/Diagnostic.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -36,8 +35,6 @@ #include "clang/Lex/TokenLexer.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" @@ -47,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/clang/lib/Lex/PreprocessingRecord.cpp b/clang/lib/Lex/PreprocessingRecord.cpp index be5aac7ef31b886a1f8fb7a47ae91e1dc68056af..f76155b1c45d6fc66f47d16b92cc19f5a827f793 100644 --- a/clang/lib/Lex/PreprocessingRecord.cpp +++ b/clang/lib/Lex/PreprocessingRecord.cpp @@ -20,12 +20,9 @@ #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Token.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Capacity.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" -#include #include #include #include diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index ecc5166d7b814c9b0be0b681d8c2dba0c6dd7188..5ac5e6feae1443d12164ab953f7e3457486456f0 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -27,7 +27,6 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/FileManager.h" -#include "clang/Basic/FileSystemStatCache.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -55,10 +54,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/clang/lib/Lex/PreprocessorLexer.cpp b/clang/lib/Lex/PreprocessorLexer.cpp index 7551ba235fe9b85b331c913c752e2d4dacb418b8..3f483c56f8b12623e96b8fa81b331983155c6c74 100644 --- a/clang/lib/Lex/PreprocessorLexer.cpp +++ b/clang/lib/Lex/PreprocessorLexer.cpp @@ -12,7 +12,6 @@ #include "clang/Lex/PreprocessorLexer.h" #include "clang/Basic/SourceManager.h" -#include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/Token.h" #include diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 856d5682727fe3db12655188183270eac45d456f..6e93416e01c0c0e09954db4bda1a3b121b40d546 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -26,7 +26,6 @@ #include "clang/Lex/VariadicMacroSupport.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" #include diff --git a/clang/lib/Parse/ParseAST.cpp b/clang/lib/Parse/ParseAST.cpp index e008cc0e38cedaf5522e00c8a499d94fd6fa3e0c..761f84070681e6268f57de2323dfe9e42bf2b374 100644 --- a/clang/lib/Parse/ParseAST.cpp +++ b/clang/lib/Parse/ParseAST.cpp @@ -15,7 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Stmt.h" -#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Parse/Parser.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index b461743833c82a80b398c0be9b8f9c7c741ac49b..2ec66fe95708e1c9afbce3e8f83bfd3338d58182 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -11,7 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/DeclTemplate.h" -#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index b5f241739fa9d49983394cda9b9c43783fc52960..52404eae9b901f932481419f01362201216c82c0 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -17,9 +17,9 @@ #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 60aab1411a96c58dcb38034c320fba0a8045cdd8..010ac9c1a3e3a9cae4be35b24f6f27c3baacc9f9 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -16,11 +16,11 @@ #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index ce3624f366a2a19f18ba8fae898a5a3e4f6cf54f..03a58048e53a949cbaf311df9f0dd7c54bb21d44 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -13,11 +13,11 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/LiteralSupport.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp index b36ea4012c26e147ff772b51ddd51bdd2f646bf9..46a37e943535332da464a0bb7a5144ab85d4a033 100644 --- a/clang/lib/Parse/ParseHLSL.cpp +++ b/clang/lib/Parse/ParseHLSL.cpp @@ -12,7 +12,7 @@ #include "clang/AST/Attr.h" #include "clang/Basic/AttributeCommonInfo.h" -#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/SemaHLSL.h" diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp index 07f133408c38794d3141eb00f3e1dccfdbc9e466..63b1d7bd9db53e1a265444d39c2f9839c9ad1f3d 100644 --- a/clang/lib/Parse/ParseInit.cpp +++ b/clang/lib/Parse/ParseInit.cpp @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/Designator.h" diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index e69fa152481982d9f5a5d43c7adc05fd64c26d34..bcbf4dfbabafa87bf945971f41166bd18f0ad034 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -15,8 +15,8 @@ #include "clang/AST/ODRDiagsEmitter.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" @@ -1454,7 +1454,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, SmallVector KeyIdents; SmallVector KeyLocs; - SmallVector ObjCParamInfo; + SmallVector ArgInfos; ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | Scope::FunctionDeclarationScope | Scope::DeclScope); @@ -1495,9 +1495,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfo.NameLoc = Tok.getLocation(); ConsumeToken(); // Eat the identifier. - ParmVarDecl *Param = Actions.ObjC().ActOnMethodParmDeclaration( - getCurScope(), ArgInfo, ObjCParamInfo.size(), MethodDefinition); - ObjCParamInfo.push_back(Param); + ArgInfos.push_back(ArgInfo); KeyIdents.push_back(SelIdent); KeyLocs.push_back(selLoc); @@ -1557,6 +1555,17 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, nullptr)); } + // Turn ArgInfos into parameters. This must happen after parsing all + // parameters for bug compatibility with previous versions of Clang. (For + // instance, if a method declares a parameter called "id", that parameter must + // not shadow the "id" type.) + SmallVector ObjCParamInfo; + for (auto &ArgInfo : ArgInfos) { + ParmVarDecl *Param = Actions.ObjC().ActOnMethodParmDeclaration( + getCurScope(), ArgInfo, ObjCParamInfo.size(), MethodDefinition); + ObjCParamInfo.push_back(Param); + } + // FIXME: Add support for optional parameter list... // If attributes exist after the method, parse them. MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0), diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index c29779cc917312e7f21f5dcc97321a4dc9054a78..b64c72904b19a461c57fd0c41b54109ab5b549aa 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/OpenACCClause.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenACCKinds.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/SemaOpenACC.h" @@ -571,6 +571,9 @@ bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) { case OpenACCDirectiveKind::Parallel: case OpenACCDirectiveKind::Serial: case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: case OpenACCDirectiveKind::Loop: return true; } @@ -582,6 +585,9 @@ unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) { case OpenACCDirectiveKind::Parallel: case OpenACCDirectiveKind::Serial: case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: // Mark this as a BreakScope/ContinueScope as well as a compute construct // so that we can diagnose trying to 'break'/'continue' inside of one. return Scope::BreakScope | Scope::ContinueScope | diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 7f2881d44bb15f5fd5f7bb71a015f00216f07be8..61a18c01eaaf3d14833b0c94df3362ebbc54d05b 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -13,10 +13,10 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/OpenMPClause.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 12fed448d477c0229c41ab3d2b602056ee7ea1ee..21ebff1e505595af56d711d876191fb2693e27fe 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -11,12 +11,12 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/PragmaKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/Token.h" #include "clang/Parse/LoopHint.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 0953cfc3c017efe27dbf93a47c45462164883004..b2cb3d71e09f95a07a6127b2e499f58b00f3a294 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -13,7 +13,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" -#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index e4bc9f4aa41ceef68ad41eb17be213238afff8be..49e380642331bfeb76d2c48897490b085591f827 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/DiagnosticParse.h" #include "clang/Parse/Parser.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/ParsedTemplate.h" using namespace clang; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 04c2f1d380bc48b7ff3d35daa8adebd3f5e31988..36e56a92c3092e423c8a4349f74ad73d853e033f 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -15,8 +15,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/DeclTemplate.h" +#include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/FileManager.h" -#include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index c76733e9a774b683c275ccf1f038e119c9883c79..075c0df3f549611c56422d1a0e1763f86c42c60d 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -16,16 +16,15 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" -#include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" #include "clang/Analysis/Analyses/CalledOnceCheck.h" @@ -48,10 +47,8 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLFunctionalExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" #include #include #include @@ -1067,81 +1064,79 @@ static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, } namespace { - class FallthroughMapper : public RecursiveASTVisitor { - public: - FallthroughMapper(Sema &S) - : FoundSwitchStatements(false), - S(S) { - } +class FallthroughMapper : public DynamicRecursiveASTVisitor { +public: + FallthroughMapper(Sema &S) : FoundSwitchStatements(false), S(S) { + ShouldWalkTypesOfTypeLocs = false; + } - bool foundSwitchStatements() const { return FoundSwitchStatements; } + bool foundSwitchStatements() const { return FoundSwitchStatements; } - void markFallthroughVisited(const AttributedStmt *Stmt) { - bool Found = FallthroughStmts.erase(Stmt); - assert(Found); - (void)Found; - } + void markFallthroughVisited(const AttributedStmt *Stmt) { + bool Found = FallthroughStmts.erase(Stmt); + assert(Found); + (void)Found; + } + + typedef llvm::SmallPtrSet AttrStmts; - typedef llvm::SmallPtrSet AttrStmts; + const AttrStmts &getFallthroughStmts() const { return FallthroughStmts; } - const AttrStmts &getFallthroughStmts() const { - return FallthroughStmts; + void fillReachableBlocks(CFG *Cfg) { + assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); + std::deque BlockQueue; + + ReachableBlocks.insert(&Cfg->getEntry()); + BlockQueue.push_back(&Cfg->getEntry()); + // Mark all case blocks reachable to avoid problems with switching on + // constants, covered enums, etc. + // These blocks can contain fall-through annotations, and we don't want to + // issue a warn_fallthrough_attr_unreachable for them. + for (const auto *B : *Cfg) { + const Stmt *L = B->getLabel(); + if (isa_and_nonnull(L) && ReachableBlocks.insert(B).second) + BlockQueue.push_back(B); } - void fillReachableBlocks(CFG *Cfg) { - assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); - std::deque BlockQueue; - - ReachableBlocks.insert(&Cfg->getEntry()); - BlockQueue.push_back(&Cfg->getEntry()); - // Mark all case blocks reachable to avoid problems with switching on - // constants, covered enums, etc. - // These blocks can contain fall-through annotations, and we don't want to - // issue a warn_fallthrough_attr_unreachable for them. - for (const auto *B : *Cfg) { - const Stmt *L = B->getLabel(); - if (isa_and_nonnull(L) && ReachableBlocks.insert(B).second) + while (!BlockQueue.empty()) { + const CFGBlock *P = BlockQueue.front(); + BlockQueue.pop_front(); + for (const CFGBlock *B : P->succs()) { + if (B && ReachableBlocks.insert(B).second) BlockQueue.push_back(B); } - - while (!BlockQueue.empty()) { - const CFGBlock *P = BlockQueue.front(); - BlockQueue.pop_front(); - for (const CFGBlock *B : P->succs()) { - if (B && ReachableBlocks.insert(B).second) - BlockQueue.push_back(B); - } - } } + } - bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt, - bool IsTemplateInstantiation) { - assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); + bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt, + bool IsTemplateInstantiation) { + assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); - int UnannotatedCnt = 0; - AnnotatedCnt = 0; + int UnannotatedCnt = 0; + AnnotatedCnt = 0; - std::deque BlockQueue(B.pred_begin(), B.pred_end()); - while (!BlockQueue.empty()) { - const CFGBlock *P = BlockQueue.front(); - BlockQueue.pop_front(); - if (!P) continue; + std::deque BlockQueue(B.pred_begin(), B.pred_end()); + while (!BlockQueue.empty()) { + const CFGBlock *P = BlockQueue.front(); + BlockQueue.pop_front(); + if (!P) + continue; - const Stmt *Term = P->getTerminatorStmt(); - if (isa_and_nonnull(Term)) - continue; // Switch statement, good. + const Stmt *Term = P->getTerminatorStmt(); + if (isa_and_nonnull(Term)) + continue; // Switch statement, good. - const SwitchCase *SW = dyn_cast_or_null(P->getLabel()); - if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) - continue; // Previous case label has no statements, good. + const SwitchCase *SW = dyn_cast_or_null(P->getLabel()); + if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) + continue; // Previous case label has no statements, good. - const LabelStmt *L = dyn_cast_or_null(P->getLabel()); - if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) - continue; // Case label is preceded with a normal label, good. + const LabelStmt *L = dyn_cast_or_null(P->getLabel()); + if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) + continue; // Case label is preceded with a normal label, good. - if (!ReachableBlocks.count(P)) { - for (const CFGElement &Elem : llvm::reverse(*P)) { - if (std::optional CS = Elem.getAs()) { + if (!ReachableBlocks.count(P)) { + for (const CFGElement &Elem : llvm::reverse(*P)) { + if (std::optional CS = Elem.getAs()) { if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { // Don't issue a warning for an unreachable fallthrough // attribute in template instantiations as it may not be @@ -1154,8 +1149,8 @@ namespace { break; } // Don't care about other unreachable statements. - } } + } // If there are no unreachable statements, this may be a special // case in CFG: // case X: { @@ -1165,7 +1160,7 @@ namespace { // // <<<< This place is represented by a 'hanging' CFG block. // case Y: continue; - } + } const Stmt *LastStmt = getLastStmt(*P); if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { @@ -1182,30 +1177,27 @@ namespace { } ++UnannotatedCnt; - } - return !!UnannotatedCnt; } + return !!UnannotatedCnt; + } - // RecursiveASTVisitor setup. - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool VisitAttributedStmt(AttributedStmt *S) { - if (asFallThroughAttr(S)) - FallthroughStmts.insert(S); - return true; - } + bool VisitAttributedStmt(AttributedStmt *S) override { + if (asFallThroughAttr(S)) + FallthroughStmts.insert(S); + return true; + } - bool VisitSwitchStmt(SwitchStmt *S) { - FoundSwitchStatements = true; - return true; - } + bool VisitSwitchStmt(SwitchStmt *S) override { + FoundSwitchStatements = true; + return true; + } // We don't want to traverse local type declarations. We analyze their // methods separately. - bool TraverseDecl(Decl *D) { return true; } + bool TraverseDecl(Decl *D) override { return true; } // We analyze lambda bodies separately. Skip them here. - bool TraverseLambdaExpr(LambdaExpr *LE) { + bool TraverseLambdaExpr(LambdaExpr *LE) override { // Traverse the captures, but not the body. for (const auto C : zip(LE->captures(), LE->capture_inits())) TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); @@ -1242,7 +1234,7 @@ namespace { AttrStmts FallthroughStmts; Sema &S; llvm::SmallPtrSet ReachableBlocks; - }; +}; } // anonymous namespace static StringRef getFallthroughAttrSpelling(Preprocessor &PP, @@ -2270,19 +2262,28 @@ public: MsgParam = 5; } else if (const auto *ECE = dyn_cast(Operation)) { QualType destType = ECE->getType(); + bool destTypeComplete = true; + if (!isa(destType)) return; + destType = destType.getTypePtr()->getPointeeType(); + if (const auto *D = destType->getAsTagDecl()) + destTypeComplete = D->isCompleteDefinition(); - const uint64_t dSize = - Ctx.getTypeSize(destType.getTypePtr()->getPointeeType()); + // If destination type is incomplete, it is unsafe to cast to anyway, no + // need to check its type: + if (destTypeComplete) { + const uint64_t dSize = Ctx.getTypeSize(destType); + QualType srcType = ECE->getSubExpr()->getType(); - QualType srcType = ECE->getSubExpr()->getType(); - const uint64_t sSize = - Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType()); + assert(srcType->isPointerType()); - if (sSize >= dSize) - return; + const uint64_t sSize = + Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType()); + if (sSize >= dSize) + return; + } if (const auto *CE = dyn_cast( ECE->getSubExpr()->IgnoreParens())) { D = CE->getMethodDecl(); @@ -2502,15 +2503,18 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { // An AST Visitor that calls a callback function on each callable DEFINITION // that is NOT in a dependent context: -class CallableVisitor : public RecursiveASTVisitor { +class CallableVisitor : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; public: CallableVisitor(llvm::function_ref Callback) - : Callback(Callback) {} + : Callback(Callback) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; + } - bool VisitFunctionDecl(FunctionDecl *Node) { + bool VisitFunctionDecl(FunctionDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl // `FunctionDecl->hasBody()` returns true if the function has a body @@ -2521,14 +2525,14 @@ public: return true; } - bool VisitBlockDecl(BlockDecl *Node) { + bool VisitBlockDecl(BlockDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl Callback(Node); return true; } - bool VisitObjCMethodDecl(ObjCMethodDecl *Node) { + bool VisitObjCMethodDecl(ObjCMethodDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl if (Node->hasBody()) @@ -2536,12 +2540,9 @@ public: return true; } - bool VisitLambdaExpr(LambdaExpr *Node) { + bool VisitLambdaExpr(LambdaExpr *Node) override { return VisitFunctionDecl(Node->getCallOperator()); } - - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } }; void clang::sema::AnalysisBasedWarnings::IssueWarnings( diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp index a1a402b4a2b53077a9cddacafc6f281020851636..8886e5e307ddf86715fce39dfca845e8e1a9c86f 100644 --- a/clang/lib/Sema/CheckExprLifetime.cpp +++ b/clang/lib/Sema/CheckExprLifetime.cpp @@ -45,10 +45,14 @@ enum LifetimeKind { /// a default member initializer), the program is ill-formed. LK_MemInitializer, - /// The lifetime of a temporary bound to this entity probably ends too soon, + /// The lifetime of a temporary bound to this entity may end too soon, /// because the entity is a pointer and we assign the address of a temporary /// object to it. LK_Assignment, + + /// The lifetime of a temporary bound to this entity may end too soon, + /// because the entity may capture the reference to a temporary object. + LK_LifetimeCapture, }; using LifetimeResult = llvm::PointerIntPair; @@ -1095,9 +1099,7 @@ static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) { } static bool isAssignmentOperatorLifetimeBound(CXXMethodDecl *CMD) { - if (!CMD) - return false; - return isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 && + return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 && CMD->getParamDecl(0)->hasAttr(); } @@ -1110,13 +1112,14 @@ static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, isAssignmentOperatorLifetimeBound(Entity.AssignmentOperator))); } -static void checkExprLifetimeImpl(Sema &SemaRef, - const InitializedEntity *InitEntity, - const InitializedEntity *ExtendingEntity, - LifetimeKind LK, - const AssignedEntity *AEntity, Expr *Init) { - assert((AEntity && LK == LK_Assignment) || - (InitEntity && LK != LK_Assignment)); +static void +checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, + const InitializedEntity *ExtendingEntity, LifetimeKind LK, + const AssignedEntity *AEntity, + const CapturingEntity *CapEntity, Expr *Init) { + assert(!AEntity || LK == LK_Assignment); + assert(!CapEntity || LK == LK_LifetimeCapture); + assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture)); // If this entity doesn't have an interesting lifetime, don't bother looking // for temporaries within its initializer. if (LK == LK_FullExpression) @@ -1199,12 +1202,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef, break; } + case LK_LifetimeCapture: { + // The captured entity has lifetime beyond the full-expression, + // and the capturing entity does too, so don't warn. + if (!MTE) + return false; + if (CapEntity->Entity) + SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured) + << CapEntity->Entity << DiagRange; + else + SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown) + << DiagRange; + return false; + } + case LK_Assignment: { if (!MTE || pathContainsInit(Path)) return false; - assert(shouldLifetimeExtendThroughPath(Path) == - PathLifetimeKind::NoExtend && - "No lifetime extension for assignments"); if (IsGslPtrValueFromGslTempOwner) SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment) << AEntity->LHS << DiagRange; @@ -1413,13 +1427,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef, }; llvm::SmallVector Path; - if (LK == LK_Assignment && - shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity)) { - Path.push_back( - {isAssignmentOperatorLifetimeBound(AEntity->AssignmentOperator) - ? IndirectLocalPathEntry::LifetimeBoundCall - : IndirectLocalPathEntry::GslPointerAssignment, - Init}); + switch (LK) { + case LK_Assignment: { + if (shouldRunGSLAssignmentAnalysis(SemaRef, *AEntity)) + Path.push_back( + {isAssignmentOperatorLifetimeBound(AEntity->AssignmentOperator) + ? IndirectLocalPathEntry::LifetimeBoundCall + : IndirectLocalPathEntry::GslPointerAssignment, + Init}); + break; + } + case LK_LifetimeCapture: { + if (isPointerLikeType(Init->getType())) + Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init}); + break; + } + default: + break; } if (Init->isGLValue()) @@ -1432,23 +1456,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef, /*RevisitSubinits=*/!InitEntity); } -void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity, +void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init) { auto LTResult = getEntityLifetime(&Entity); LifetimeKind LK = LTResult.getInt(); const InitializedEntity *ExtendingEntity = LTResult.getPointer(); checkExprLifetimeImpl(SemaRef, &Entity, ExtendingEntity, LK, - /*AEntity*/ nullptr, Init); + /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init); } void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init) { checkExprLifetimeImpl(SemaRef, &Entity, nullptr, LK_MustTail, - /*AEntity*/ nullptr, Init); + /*AEntity=*/nullptr, /*CapEntity=*/nullptr, Init); } -void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity, - Expr *Init) { +void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, + Expr *Init) { bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics().isIgnored( diag::warn_dangling_pointer_assignment, SourceLocation()); bool RunAnalysis = (EnableDanglingPointerAssignment && @@ -1460,7 +1484,20 @@ void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity, checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr, /*ExtendingEntity=*/nullptr, LK_Assignment, &Entity, - Init); + /*CapEntity=*/nullptr, Init); +} + +void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, + Expr *Init) { + if (SemaRef.getDiagnostics().isIgnored(diag::warn_dangling_reference_captured, + SourceLocation()) && + SemaRef.getDiagnostics().isIgnored( + diag::warn_dangling_reference_captured_by_unknown, SourceLocation())) + return; + return checkExprLifetimeImpl(SemaRef, /*InitEntity=*/nullptr, + /*ExtendingEntity=*/nullptr, LK_LifetimeCapture, + /*AEntity=*/nullptr, + /*CapEntity=*/&Entity, Init); } } // namespace clang::sema diff --git a/clang/lib/Sema/CheckExprLifetime.h b/clang/lib/Sema/CheckExprLifetime.h index 903f312f3533e5340613d6a9e9e1838121da70ba..38b7061988dc782d50669cfbf8e4313ee46d77cc 100644 --- a/clang/lib/Sema/CheckExprLifetime.h +++ b/clang/lib/Sema/CheckExprLifetime.h @@ -25,15 +25,31 @@ struct AssignedEntity { CXXMethodDecl *AssignmentOperator = nullptr; }; +struct CapturingEntity { + // In an function call involving a lifetime capture, this would be the + // argument capturing the lifetime of another argument. + // void addToSet(std::string_view sv [[clang::lifetime_capture_by(setsv)]], + // set& setsv); + // set setsv; + // addToSet(std::string(), setsv); // Here 'setsv' is the 'Entity'. + // + // This is 'nullptr' when the capturing entity is 'global' or 'unknown'. + Expr *Entity = nullptr; +}; + /// Check that the lifetime of the given expr (and its subobjects) is /// sufficient for initializing the entity, and perform lifetime extension /// (when permitted) if not. -void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity, +void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init); /// Check that the lifetime of the given expr (and its subobjects) is /// sufficient for assigning to the entity. -void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init); +void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, + Expr *Init); + +void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, + Expr *Init); /// Check that the lifetime of the given expr (and its subobjects) is /// sufficient, assuming that it is passed as an argument to a musttail diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp index 91713d71786ee5eeffa9b050f2d72d6593490aec..c4e5ef0d75af7563a7b5df6c617eff81e9826b5a 100644 --- a/clang/lib/Sema/CodeCompleteConsumer.cpp +++ b/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -21,15 +21,11 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include #include diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index d98dde450de59c6f215014df48ffa6a2125a97e1..f790335800c53acda9f208c70aadf8339b01936d 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -22,9 +22,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Sema.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include using namespace clang; diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index cac15b974a276e0522c4e13f99b5e52ee4bfd235..a14e7d50a6043ff18be5307747285286c39a5fe4 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -139,7 +139,7 @@ struct BuiltinTypeDeclBuilder { Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK); if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs, AttributedResTy)) - addMemberVariable("h", AttributedResTy, {ResourceAttr}, Access); + addMemberVariable("__handle", AttributedResTy, {ResourceAttr}, Access); return *this; } @@ -212,11 +212,11 @@ struct BuiltinTypeDeclBuilder { // Subscript operators return references to elements, const makes the // reference and method const so that the underlying data is not mutable. - ReturnTy = AST.getLValueReferenceType(ReturnTy); if (IsConst) { ExtInfo.TypeQuals.addConst(); ReturnTy.addConst(); } + ReturnTy = AST.getLValueReferenceType(ReturnTy); QualType MethodTy = AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo); @@ -480,8 +480,8 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, - ResourceKind::TypedBuffer, - /*IsROV=*/false, /*RawBuffer=*/false) + ResourceKind::TypedBuffer, /*IsROV=*/false, + /*RawBuffer=*/false) .addArraySubscriptOperators() .completeDefinition(); }); @@ -503,8 +503,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer, - /*IsROV=*/false, - /*RawBuffer=*/true) + /*IsROV=*/false, /*RawBuffer=*/true) .addArraySubscriptOperators() .completeDefinition(); }); @@ -514,8 +513,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, - /*IsROV=*/false, - /*RawBuffer=*/true) + /*IsROV=*/false, /*RawBuffer=*/true) .addArraySubscriptOperators() .completeDefinition(); }); @@ -526,8 +524,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, - /*IsROV=*/false, - /*RawBuffer=*/true) + /*IsROV=*/false, /*RawBuffer=*/true) .completeDefinition(); }); @@ -537,8 +534,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, - /*IsROV=*/false, - /*RawBuffer=*/true) + /*IsROV=*/false, /*RawBuffer=*/true) .completeDefinition(); }); @@ -547,9 +543,8 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { .addSimpleTemplateParams(*SemaPtr, {"element_type"}) .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { - setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, - ResourceKind::TypedBuffer, /*IsROV=*/true, - /*RawBuffer=*/true) + setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer, + /*IsROV=*/true, /*RawBuffer=*/true) .addArraySubscriptOperators() .completeDefinition(); }); diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index 00fdffca4e9ea9ffaae2f00dff3f84e699e7bcf3..d465599450e7ffc9cea24bd6bcb5d7b76daf59aa 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -179,9 +179,9 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) { } } - const Expr *Init = VD->getInit(); - if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init && - !Init->containsErrors()) { + if (const Expr *Init = VD->getInit(); S.Context.getLangOpts().CPlusPlus && + VD->hasLocalStorage() && Init && + !Init->containsErrors()) { // C++11 [stmt.dcl]p3: // A program that jumps from a point where a variable with automatic // storage duration is not in scope to a point where it is in scope @@ -616,6 +616,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, return; } + case Stmt::OpenACCCombinedConstructClass: { + unsigned NewParentScope = Scopes.size(); + OpenACCCombinedConstruct *CC = cast(S); + Scopes.push_back(GotoScope( + ParentScope, diag::note_acc_branch_into_compute_construct, + diag::note_acc_branch_out_of_compute_construct, CC->getBeginLoc())); + BuildScopeInformation(CC->getLoop(), NewParentScope); + return; + } + default: if (auto *ED = dyn_cast(S)) { if (!ED->isStandaloneDirective()) { diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp index 2109494aa5889d9e7c24f085e1b0d9cf15675117..eadc6ed6e6f581f5bf48cb7ad95af9218f506808 100644 --- a/clang/lib/Sema/ParsedAttr.cpp +++ b/clang/lib/Sema/ParsedAttr.cpp @@ -16,9 +16,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaInternal.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include #include #include diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index 12fb7060727233f4b6b6c25513932e95ff639f32..d089836fa36dd9b38c6840b473dd95a216f32013 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -13,7 +13,6 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 2b51765e80864acb677bf2407158d53ce0adb2ac..942e7ece4283e3be400d5c37af3f4af93d8079c3 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -27,13 +27,11 @@ #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" -#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/CXXFieldCollector.h" -#include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Initialization.h" @@ -51,7 +49,6 @@ #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaHexagon.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLoongArch.h" #include "clang/Sema/SemaM68k.h" #include "clang/Sema/SemaMIPS.h" diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 5bb58d6c98be957d6466ce5a47afe4406717ec63..cbc092195ad30e692bc4173f3fadd6b5bdb13488 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -18,7 +18,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaSwift.h" #include @@ -647,6 +646,11 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info, D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable")); } + if (auto Escapable = Info.isSwiftEscapable()) { + D->addAttr(SwiftAttrAttr::Create(S.Context, + *Escapable ? "Escapable" : "~Escapable")); + } + if (auto Extensibility = Info.EnumExtensibility) { using api_notes::EnumExtensibilityKind; bool ShouldAddAttribute = (*Extensibility != EnumExtensibilityKind::None); diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index c3a6e5ef8a9d44a9bec89ac7df3aaf0bef66b903..3e93b38143f3b3830eb5d114ad5045c7c0df63b9 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -907,7 +907,7 @@ bool SemaARM::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, // Issue a warning if the cast is dodgy. CastKind CastNeeded = CK_NoOp; - if (!AddrType.isAtLeastAsQualifiedAs(ValType)) { + if (!AddrType.isAtLeastAsQualifiedAs(ValType, getASTContext())) { CastNeeded = CK_BitCast; Diag(DRE->getBeginLoc(), diag::ext_typecheck_convert_discards_qualifiers) << PointerArg->getType() << Context.getPointerType(AddrType) diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index df6edb21a50dee956e4b0849f354e8afe65274a3..f79d9a758e7af3bf35a1ac8a202190ac1acb365a 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -21,7 +21,6 @@ #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/STLForwardCompat.h" using namespace clang; diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 68a8dfaf1f6183cb819dab36ff3a5a208262bb25..9fbad7ed67ccbe27f360192a9bf6b0322776be80 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -17,7 +17,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/SemaInternal.h" #include using namespace clang; diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 076d3489fa94383b08c182a1f81801ab64518bb8..c806b832dec7a7e61a37f8abc279fa1fb5a6889c 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -13,7 +13,9 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtObjC.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" @@ -741,11 +743,11 @@ bool isBodyLikeChildStmt(const Stmt *S, const Stmt *Parent) { } } -class StmtUSEFinder : public RecursiveASTVisitor { +class StmtUSEFinder : public DynamicRecursiveASTVisitor { const Stmt *Target; public: - bool VisitStmt(Stmt *S) { return S != Target; } + bool VisitStmt(Stmt *S) override { return S != Target; } /// Returns true if the given statement is present in the given declaration. static bool isContained(const Stmt *Target, const Decl *D) { @@ -757,11 +759,11 @@ public: /// Traverses the AST and finds the last statement that used a given /// declaration. -class LastDeclUSEFinder : public RecursiveASTVisitor { +class LastDeclUSEFinder : public DynamicRecursiveASTVisitor { const Decl *D; public: - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { if (DRE->getDecl() == D) return false; return true; @@ -785,10 +787,7 @@ public: /// to a partially available declaration. Whenever we encounter an \c if of the /// form: \c if(@available(...)), we use the version from the condition to visit /// the then statement. -class DiagnoseUnguardedAvailability - : public RecursiveASTVisitor { - typedef RecursiveASTVisitor Base; - +class DiagnoseUnguardedAvailability : public DynamicRecursiveASTVisitor { Sema &SemaRef; Decl *Ctx; @@ -806,26 +805,26 @@ public: SemaRef.Context.getTargetInfo().getPlatformMinVersion()); } - bool TraverseStmt(Stmt *S) { + bool TraverseStmt(Stmt *S) override { if (!S) return true; StmtStack.push_back(S); - bool Result = Base::TraverseStmt(S); + bool Result = DynamicRecursiveASTVisitor::TraverseStmt(S); StmtStack.pop_back(); return Result; } void IssueDiagnostics(Stmt *S) { TraverseStmt(S); } - bool TraverseIfStmt(IfStmt *If); + bool TraverseIfStmt(IfStmt *If) override; // for 'case X:' statements, don't bother looking at the 'X'; it can't lead // to any useful diagnostics. - bool TraverseCaseStmt(CaseStmt *CS) { return TraverseStmt(CS->getSubStmt()); } - - bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *PRE) { return true; } + bool TraverseCaseStmt(CaseStmt *CS) override { + return TraverseStmt(CS->getSubStmt()); + } - bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { + bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override { if (ObjCMethodDecl *D = Msg->getMethodDecl()) { ObjCInterfaceDecl *ID = nullptr; QualType ReceiverTy = Msg->getClassReceiver(); @@ -838,25 +837,25 @@ public: return true; } - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { DiagnoseDeclAvailability(DRE->getDecl(), SourceRange(DRE->getBeginLoc(), DRE->getEndLoc())); return true; } - bool VisitMemberExpr(MemberExpr *ME) { + bool VisitMemberExpr(MemberExpr *ME) override { DiagnoseDeclAvailability(ME->getMemberDecl(), SourceRange(ME->getBeginLoc(), ME->getEndLoc())); return true; } - bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { + bool VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) override { SemaRef.Diag(E->getBeginLoc(), diag::warn_at_available_unchecked_use) << (!SemaRef.getLangOpts().ObjC); return true; } - bool VisitTypeLoc(TypeLoc Ty); + bool VisitTypeLoc(TypeLoc Ty) override; }; void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( @@ -1038,7 +1037,7 @@ bool DiagnoseUnguardedAvailability::TraverseIfStmt(IfStmt *If) { ExtractedAvailabilityExpr IfCond = extractAvailabilityExpr(If->getCond()); if (!IfCond.E) { // This isn't an availability checking 'if', we can just continue. - return Base::TraverseIfStmt(If); + return DynamicRecursiveASTVisitor::TraverseIfStmt(If); } VersionTuple CondVersion = IfCond.E->getVersion(); diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index ec37c0df56c671d3265f812c227942cfeb938197..35f28bf1bd61a260b7ab5dda628c73bee01c0b43 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -20,8 +20,6 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallVector.h" @@ -659,9 +657,9 @@ void SemaCUDA::checkAllowedInitializer(VarDecl *VD) { // Return early if VD is inside a non-instantiated template function since // the implicit constructor is not defined yet. if (const FunctionDecl *FD = - dyn_cast_or_null(VD->getDeclContext())) - if (FD->isDependentContext()) - return; + dyn_cast_or_null(VD->getDeclContext()); + FD && FD->isDependentContext()) + return; // Do not check dependent variables since the ctor/dtor/initializer are not // determined. Do it after instantiation. diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 5b2d65247e72e55dd5eafb7924da08f5daaf6594..f04f7f9929442c51c8c7f9e39a237b87260a96a1 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -18,7 +18,6 @@ #include "clang/Basic/PartialDiagnostic.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Lookup.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" using namespace clang; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 6ac6201843476b5031abd42224d10a2fb288e877..f98857f852b5af392cc41e19c9ffff06a68b468a 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -23,7 +23,6 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaRISCV.h" #include "llvm/ADT/SmallVector.h" @@ -731,7 +730,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, *CastAwayQualifiers = SrcCvrQuals - DestCvrQuals; // If we removed a cvr-qualifier, this is casting away 'constness'. - if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals)) { + if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals, + Self.getASTContext())) { if (TheOffendingSrcType) *TheOffendingSrcType = PrevUnwrappedSrcType; if (TheOffendingDestType) @@ -889,7 +889,7 @@ void CastOperation::CheckDynamicCast() { assert(SrcRecord && "Bad source pointee slipped through."); // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness. - if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { + if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee, Self.getASTContext())) { Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) << CT_Dynamic << OrigSrcType << this->DestType << OpRange; SrcExpr = ExprError(); @@ -1463,7 +1463,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, SrcPointeeQuals.removeObjCGCAttr(); SrcPointeeQuals.removeObjCLifetime(); if (DestPointeeQuals != SrcPointeeQuals && - !DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals)) { + !DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals, + Self.getASTContext())) { msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -1695,7 +1696,8 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, // FIXME: Being 100% compliant here would be nice to have. // Must preserve cv, as always, unless we're in C-style mode. - if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) { + if (!CStyle && + !DestType.isAtLeastAsQualifiedAs(SrcType, Self.getASTContext())) { msg = diag::err_bad_cxx_cast_qualifiers_away; return TC_Failed; } @@ -2524,7 +2526,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, assert(SrcType->isPointerType() && DestType->isPointerType()); if (!CStyle && !DestType->getPointeeType().getQualifiers().isAddressSpaceSupersetOf( - SrcType->getPointeeType().getQualifiers())) { + SrcType->getPointeeType().getQualifiers(), Self.getASTContext())) { SuccessResult = TC_Failed; } } else if (IsLValueCast) { @@ -2631,7 +2633,8 @@ static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr, return TC_NotApplicable; auto SrcPointeeType = SrcPtrType->getPointeeType(); auto DestPointeeType = DestPtrType->getPointeeType(); - if (!DestPointeeType.isAddressSpaceOverlapping(SrcPointeeType)) { + if (!DestPointeeType.isAddressSpaceOverlapping(SrcPointeeType, + Self.getASTContext())) { msg = diag::err_bad_cxx_cast_addr_space_mismatch; return TC_Failed; } @@ -2676,7 +2679,8 @@ void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) { QualType SrcPPointee = SrcPPtr->getPointeeType(); if (Nested ? DestPPointee.getAddressSpace() != SrcPPointee.getAddressSpace() - : !DestPPointee.isAddressSpaceOverlapping(SrcPPointee)) { + : !DestPPointee.isAddressSpaceOverlapping(SrcPPointee, + Self.getASTContext())) { Self.Diag(OpRange.getBegin(), DiagID) << SrcType << DestType << AssignmentAction::Casting << SrcExpr.get()->getSourceRange(); @@ -3283,7 +3287,8 @@ void CastOperation::CheckBuiltinBitCast() { CharUnits SourceSize = Self.Context.getTypeSizeInChars(SrcType); if (DestSize != SourceSize) { Self.Diag(OpRange.getBegin(), diag::err_bit_cast_type_size_mismatch) - << (int)SourceSize.getQuantity() << (int)DestSize.getQuantity(); + << SrcType << DestType << (int)SourceSize.getQuantity() + << (int)DestSize.getQuantity(); SrcExpr = ExprError(); return; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 96008b14225a4cc997933084ce82bdbaa9d716c8..2fd990750ed212afe246c60d84f223d2b258af7b 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "CheckExprLifetime.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" @@ -25,7 +26,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" #include "clang/AST/FormatString.h" #include "clang/AST/IgnoreExpr.h" #include "clang/AST/NSAPI.h" @@ -38,7 +38,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/AddressSpaces.h" -#include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" @@ -50,8 +49,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/SyncScope.h" -#include "clang/Basic/TargetBuiltins.h" -#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TypeTraits.h" #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. @@ -66,7 +63,6 @@ #include "clang/Sema/SemaBPF.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaHexagon.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLoongArch.h" #include "clang/Sema/SemaMIPS.h" #include "clang/Sema/SemaNVPTX.h" @@ -93,7 +89,6 @@ #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/AtomicOrdering.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ErrorHandling.h" @@ -105,7 +100,6 @@ #include "llvm/TargetParser/RISCVTargetParser.h" #include "llvm/TargetParser/Triple.h" #include -#include #include #include #include @@ -3229,6 +3223,47 @@ void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, << ParamName << (FDecl != nullptr) << FDecl; } +void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool IsMemberFunction, + const Expr *ThisArg, + ArrayRef Args) { + if (!FD || Args.empty()) + return; + auto GetArgAt = [&](int Idx) -> const Expr * { + if (Idx == LifetimeCaptureByAttr::GLOBAL || + Idx == LifetimeCaptureByAttr::UNKNOWN) + return nullptr; + if (IsMemberFunction && Idx == 0) + return ThisArg; + return Args[Idx - IsMemberFunction]; + }; + auto HandleCaptureByAttr = [&](const LifetimeCaptureByAttr *Attr, + unsigned ArgIdx) { + if (!Attr) + return; + Expr *Captured = const_cast(GetArgAt(ArgIdx)); + for (int CapturingParamIdx : Attr->params()) { + Expr *Capturing = const_cast(GetArgAt(CapturingParamIdx)); + CapturingEntity CE{Capturing}; + // Ensure that 'Captured' outlives the 'Capturing' entity. + checkCaptureByLifetime(*this, CE, Captured); + } + }; + for (unsigned I = 0; I < FD->getNumParams(); ++I) + HandleCaptureByAttr(FD->getParamDecl(I)->getAttr(), + I + IsMemberFunction); + // Check when the implicit object param is captured. + if (IsMemberFunction) { + TypeSourceInfo *TSI = FD->getTypeSourceInfo(); + if (!TSI) + return; + AttributedTypeLoc ATL; + for (TypeLoc TL = TSI->getTypeLoc(); + (ATL = TL.getAsAdjusted()); + TL = ATL.getModifiedLoc()) + HandleCaptureByAttr(ATL.getAttrAs(), 0); + } +} + void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, const Expr *ThisArg, ArrayRef Args, bool IsMemberFunction, SourceLocation Loc, @@ -3269,7 +3304,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } } } - + if (FD) + checkLifetimeCaptureBy(FD, IsMemberFunction, ThisArg, Args); if (FDecl || Proto) { CheckNonNullArguments(*this, FDecl, Proto, Args, Loc); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 16a76ff9b5c241998e4e0ae420d3904c0abc7c7a..12da3a2cbca314812a0ea0350bd08bae29edf466 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" @@ -22,7 +23,6 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/OperationKinds.h" #include "clang/AST/QualTypeNames.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/CharInfo.h" @@ -42,14 +42,12 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaCodeCompletion.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" @@ -1246,7 +1244,8 @@ enum class OverloadCompare { BothViable, Dominates, Dominated }; static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate, const CXXMethodDecl &Incumbent, const Qualifiers &ObjectQuals, - ExprValueKind ObjectKind) { + ExprValueKind ObjectKind, + const ASTContext &Ctx) { // Base/derived shadowing is handled elsewhere. if (Candidate.getDeclContext() != Incumbent.getDeclContext()) return OverloadCompare::BothViable; @@ -1280,8 +1279,8 @@ static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate, // So make some decision based on the qualifiers. Qualifiers CandidateQual = Candidate.getMethodQualifiers(); Qualifiers IncumbentQual = Incumbent.getMethodQualifiers(); - bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual); - bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual); + bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual, Ctx); + bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual, Ctx); if (CandidateSuperset == IncumbentSuperset) return OverloadCompare::BothViable; return IncumbentSuperset ? OverloadCompare::Dominates @@ -1452,7 +1451,8 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, Result &Incumbent = Results[Entry.second]; switch (compareOverloads(*Method, *cast(Incumbent.Declaration), - ObjectTypeQualifiers, ObjectKind)) { + ObjectTypeQualifiers, ObjectKind, + CurContext->getParentASTContext())) { case OverloadCompare::Dominates: // Replace the dominated overload with this one. // FIXME: if the overload dominates multiple incumbents then we @@ -5422,7 +5422,7 @@ private: // This visitor infers members of T based on traversing expressions/types // that involve T. It is invoked with code known to be valid for T. - class ValidVisitor : public RecursiveASTVisitor { + class ValidVisitor : public DynamicRecursiveASTVisitor { ConceptInfo *Outer; const TemplateTypeParmType *T; @@ -5440,7 +5440,8 @@ private: } // In T.foo or T->foo, `foo` is a member function/variable. - bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { + bool + VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) override { const Type *Base = E->getBaseType().getTypePtr(); bool IsArrow = E->isArrow(); if (Base->isPointerType() && IsArrow) { @@ -5453,14 +5454,14 @@ private: } // In T::foo, `foo` is a static member function/variable. - bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override { if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T)) addValue(E, E->getDeclName(), Member::Colons); return true; } // In T::typename foo, `foo` is a type. - bool VisitDependentNameType(DependentNameType *DNT) { + bool VisitDependentNameType(DependentNameType *DNT) override { const auto *Q = DNT->getQualifier(); if (Q && isApprox(Q->getAsType(), T)) addType(DNT->getIdentifier()); @@ -5469,7 +5470,7 @@ private: // In T::foo::bar, `foo` must be a type. // VisitNNS() doesn't exist, and TraverseNNS isn't always called :-( - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) override { if (NNSL) { NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier(); const auto *Q = NNS->getPrefix(); @@ -5477,14 +5478,14 @@ private: addType(NNS->getAsIdentifier()); } // FIXME: also handle T::foo::bar - return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL); + return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL); } // FIXME also handle T::foo // Track the innermost caller/callee relationship so we can tell if a // nested expr is being called as a function. - bool VisitCallExpr(CallExpr *CE) { + bool VisitCallExpr(CallExpr *CE) override { Caller = CE; Callee = CE->getCallee(); return true; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 0f373da6275e7ed4d35180a0219a4f1de2f49079..1bdf3a02b2924a0b49bf864658243c3ebe882af3 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -15,14 +15,12 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprConcepts.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Overload.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" -#include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 3724aaf804c90599e7d3ab177d56ab11a2b0a564..3a22097152df564984fda6d9e21f33bb4ea0a7b6 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -25,8 +25,6 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Overload.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" -#include "llvm/ADT/SmallSet.h" using namespace clang; using namespace sema; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 55960268f08b05b28237f94daf453cd433e65f7e..fcd4ec33cb48d3b47147e62b88e37cf833d9adc2 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -24,13 +24,12 @@ #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/MangleNumberingContext.h" +#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/HLSLRuntime.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -62,7 +61,6 @@ #include "llvm/TargetParser/Triple.h" #include #include -#include #include #include @@ -6868,11 +6866,7 @@ void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) { } } -static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { - // Ensure that an auto decl is deduced otherwise the checks below might cache - // the wrong linkage. - assert(S.ParsingInitForAutoVars.count(&ND) == 0); - +static void checkWeakAttr(Sema &S, NamedDecl &ND) { // 'weak' only applies to declarations with external linkage. if (WeakAttr *Attr = ND.getAttr()) { if (!ND.isExternallyVisible()) { @@ -6880,13 +6874,18 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { ND.dropAttr(); } } +} + +static void checkWeakRefAttr(Sema &S, NamedDecl &ND) { if (WeakRefAttr *Attr = ND.getAttr()) { if (ND.isExternallyVisible()) { S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static); ND.dropAttrs(); } } +} +static void checkAliasAttr(Sema &S, NamedDecl &ND) { if (auto *VD = dyn_cast(&ND)) { if (VD->hasInit()) { if (const auto *Attr = VD->getAttr()) { @@ -6897,7 +6896,9 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { } } } +} +static void checkSelectAnyAttr(Sema &S, NamedDecl &ND) { // 'selectany' only applies to externally visible variable declarations. // It does not apply to functions. if (SelectAnyAttr *Attr = ND.getAttr()) { @@ -6907,12 +6908,17 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { ND.dropAttr(); } } +} +static void checkHybridPatchableAttr(Sema &S, NamedDecl &ND) { if (HybridPatchableAttr *Attr = ND.getAttr()) { if (!ND.isExternallyVisible()) S.Diag(Attr->getLocation(), diag::warn_attribute_hybrid_patchable_non_extern); } +} + +static void checkInheritableAttr(Sema &S, NamedDecl &ND) { if (const InheritableAttr *Attr = getDLLAttr(&ND)) { auto *VD = dyn_cast(&ND); bool IsAnonymousNS = false; @@ -6937,7 +6943,9 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { ND.setInvalidDecl(); } } +} +static void checkLifetimeBoundAttr(Sema &S, NamedDecl &ND) { // Check the attributes on the function type and function params, if any. if (const auto *FD = dyn_cast(&ND)) { // Don't declare this variable in the second operand of the for-statement; @@ -6989,6 +6997,20 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { } } +static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { + // Ensure that an auto decl is deduced otherwise the checks below might cache + // the wrong linkage. + assert(S.ParsingInitForAutoVars.count(&ND) == 0); + + checkWeakAttr(S, ND); + checkWeakRefAttr(S, ND); + checkAliasAttr(S, ND); + checkSelectAnyAttr(S, ND); + checkHybridPatchableAttr(S, ND); + checkInheritableAttr(S, ND); + checkLifetimeBoundAttr(S, ND); +} + static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NamedDecl *NewDecl, bool IsSpecialization, @@ -8328,9 +8350,15 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, return; // Only warn about certain kinds of shadowing for class members. - if (NewDC && NewDC->isRecord()) { + if (NewDC) { // In particular, don't warn about shadowing non-class members. - if (!OldDC->isRecord()) + if (NewDC->isRecord() && !OldDC->isRecord()) + return; + + // Skip shadowing check if we're in a class scope, dealing with an enum + // constant in a different context. + DeclContext *ReDC = NewDC->getRedeclContext(); + if (ReDC->isRecord() && isa(D) && !OldDC->Equals(ReDC)) return; // TODO: should we warn about static data members shadowing @@ -8341,7 +8369,6 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, // shadowing context, but that's just a false negative. } - DeclarationName Name = R.getLookupName(); // Emit warning and note. @@ -16701,6 +16728,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } } + LazyProcessLifetimeCaptureByParams(FD); inferLifetimeBoundAttribute(FD); AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(FD); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 05ee17bef4aea38614f39422a9c019d5ccf6a915..fbb20446469bce69063b3265744920fb0a73be43 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -14,23 +14,22 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Cuda.h" #include "clang/Basic/DarwinSDKInfo.h" -#include "clang/Basic/HLSLRuntime.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Attr.h" @@ -47,7 +46,6 @@ #include "clang/Sema/SemaBPF.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaM68k.h" #include "clang/Sema/SemaMIPS.h" #include "clang/Sema/SemaMSP430.h" @@ -63,7 +61,7 @@ #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Demangle/Demangle.h" -#include "llvm/IR/Assumptions.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" @@ -723,8 +721,7 @@ static void handleExcludeFromExplicitInstantiationAttr(Sema &S, Decl *D, namespace { /// Determines if a given Expr references any of the given function's /// ParmVarDecls, or the function's implicit `this` parameter (if applicable). -class ArgumentDependenceChecker - : public RecursiveASTVisitor { +class ArgumentDependenceChecker : public DynamicRecursiveASTVisitor { #ifndef NDEBUG const CXXRecordDecl *ClassType; #endif @@ -748,14 +745,14 @@ public: return Result; } - bool VisitCXXThisExpr(CXXThisExpr *E) { + bool VisitCXXThisExpr(CXXThisExpr *E) override { assert(E->getType()->getPointeeCXXRecordDecl() == ClassType && "`this` doesn't refer to the enclosing class?"); Result = true; return false; } - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { if (const auto *PVD = dyn_cast(DRE->getDecl())) if (Parms.count(PVD)) { Result = true; @@ -3867,6 +3864,119 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) { S.Context, AL, EncodingIndices.data(), EncodingIndices.size())); } +LifetimeCaptureByAttr *Sema::ParseLifetimeCaptureByAttr(const ParsedAttr &AL, + StringRef ParamName) { + // Atleast one capture by is required. + if (AL.getNumArgs() == 0) { + Diag(AL.getLoc(), diag::err_capture_by_attribute_no_entity) + << AL.getRange(); + return nullptr; + } + unsigned N = AL.getNumArgs(); + auto ParamIdents = + MutableArrayRef(new (Context) IdentifierInfo *[N], N); + auto ParamLocs = + MutableArrayRef(new (Context) SourceLocation[N], N); + bool IsValid = true; + for (unsigned I = 0; I < N; ++I) { + if (AL.isArgExpr(I)) { + Expr *E = AL.getArgAsExpr(I); + Diag(E->getExprLoc(), diag::err_capture_by_attribute_argument_unknown) + << E << E->getExprLoc(); + IsValid = false; + continue; + } + assert(AL.isArgIdent(I)); + IdentifierLoc *IdLoc = AL.getArgAsIdent(I); + if (IdLoc->Ident->getName() == ParamName) { + Diag(IdLoc->Loc, diag::err_capture_by_references_itself) << IdLoc->Loc; + IsValid = false; + continue; + } + ParamIdents[I] = IdLoc->Ident; + ParamLocs[I] = IdLoc->Loc; + } + if (!IsValid) + return nullptr; + SmallVector FakeParamIndices(N, LifetimeCaptureByAttr::INVALID); + auto *CapturedBy = + LifetimeCaptureByAttr::Create(Context, FakeParamIndices.data(), N, AL); + CapturedBy->setArgs(ParamIdents, ParamLocs); + return CapturedBy; +} + +static void handleLifetimeCaptureByAttr(Sema &S, Decl *D, + const ParsedAttr &AL) { + // Do not allow multiple attributes. + if (D->hasAttr()) { + S.Diag(AL.getLoc(), diag::err_capture_by_attribute_multiple) + << AL.getRange(); + return; + } + auto *PVD = dyn_cast(D); + assert(PVD); + auto *CaptureByAttr = S.ParseLifetimeCaptureByAttr(AL, PVD->getName()); + if (CaptureByAttr) + D->addAttr(CaptureByAttr); +} + +void Sema::LazyProcessLifetimeCaptureByParams(FunctionDecl *FD) { + bool HasImplicitThisParam = isInstanceMethod(FD); + SmallVector Attrs; + for (ParmVarDecl *PVD : FD->parameters()) + if (auto *A = PVD->getAttr()) + Attrs.push_back(A); + if (HasImplicitThisParam) { + TypeSourceInfo *TSI = FD->getTypeSourceInfo(); + if (!TSI) + return; + AttributedTypeLoc ATL; + for (TypeLoc TL = TSI->getTypeLoc(); + (ATL = TL.getAsAdjusted()); + TL = ATL.getModifiedLoc()) { + if (auto *A = ATL.getAttrAs()) + Attrs.push_back(const_cast(A)); + } + } + if (Attrs.empty()) + return; + llvm::StringMap NameIdxMapping = { + {"global", LifetimeCaptureByAttr::GLOBAL}, + {"unknown", LifetimeCaptureByAttr::UNKNOWN}}; + int Idx = 0; + if (HasImplicitThisParam) { + NameIdxMapping["this"] = 0; + Idx++; + } + for (const ParmVarDecl *PVD : FD->parameters()) + NameIdxMapping[PVD->getName()] = Idx++; + auto DisallowReservedParams = [&](StringRef Reserved) { + for (const ParmVarDecl *PVD : FD->parameters()) + if (PVD->getName() == Reserved) + Diag(PVD->getLocation(), diag::err_capture_by_param_uses_reserved_name) + << (PVD->getName() == "unknown"); + }; + for (auto *CapturedBy : Attrs) { + const auto &Entities = CapturedBy->getArgIdents(); + for (size_t I = 0; I < Entities.size(); ++I) { + StringRef Name = Entities[I]->getName(); + auto It = NameIdxMapping.find(Name); + if (It == NameIdxMapping.end()) { + auto Loc = CapturedBy->getArgLocs()[I]; + if (!HasImplicitThisParam && Name == "this") + Diag(Loc, diag::err_capture_by_implicit_this_not_available) << Loc; + else + Diag(Loc, diag::err_capture_by_attribute_argument_unknown) + << Entities[I] << Loc; + continue; + } + if (Name == "unknown" || Name == "global") + DisallowReservedParams(Name); + CapturedBy->setParamIdx(I, It->second); + } + } +} + static bool isFunctionLike(const Type &T) { // Check for explicit function types. // 'called_once' is only supported in Objective-C and it has @@ -6644,6 +6754,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_Callback: handleCallbackAttr(S, D, AL); break; + case ParsedAttr::AT_LifetimeCaptureBy: + handleLifetimeCaptureByAttr(S, D, AL); + break; case ParsedAttr::AT_CalledOnce: handleCalledOnceAttr(S, D, AL); break; @@ -7257,7 +7370,9 @@ void Sema::ProcessDeclAttributeList( // good to have a way to specify "these attributes must appear as a group", // for these. Additionally, it would be good to have a way to specify "these // attribute must never appear as a group" for attributes like cold and hot. - if (!D->hasAttr()) { + if (!(D->hasAttr() || + (D->hasAttr() && + Context.getTargetInfo().getTriple().isSPIRV()))) { // These attributes cannot be applied to a non-kernel function. if (const auto *A = D->getAttr()) { // FIXME: This emits a different error message than diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c1ba235535543191eefae3bab69def6eaba8639f..08b4f2eb4fe0e49774075730182195bd9447e0bd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -12,18 +12,17 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/ComparisonCategories.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" @@ -50,8 +49,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLForwardCompat.h" -#include "llvm/ADT/ScopeExit.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/SaveAndRestore.h" @@ -2499,10 +2496,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { assert(FD->isImmediateEscalating() && !FD->isConsteval() && "expected an immediate function"); assert(FD->hasBody() && "expected the function to have a body"); - struct ImmediateEscalatingExpressionsVisitor - : public RecursiveASTVisitor { - - using Base = RecursiveASTVisitor; + struct ImmediateEscalatingExpressionsVisitor : DynamicRecursiveASTVisitor { Sema &SemaRef; const FunctionDecl *ImmediateFn; @@ -2512,10 +2506,10 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { ImmediateEscalatingExpressionsVisitor(Sema &SemaRef, FunctionDecl *FD) : SemaRef(SemaRef), ImmediateFn(FD), - ImmediateFnIsConstructor(isa(FD)) {} - - bool shouldVisitImplicitCode() const { return true; } - bool shouldVisitLambdaBody() const { return false; } + ImmediateFnIsConstructor(isa(FD)) { + ShouldVisitImplicitCode = true; + ShouldVisitLambdaBody = false; + } void Diag(const Expr *E, const FunctionDecl *Fn, bool IsCall) { SourceLocation Loc = E->getBeginLoc(); @@ -2535,7 +2529,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { << (CurrentInit && !CurrentInit->isWritten()) << InitializedField << Range; } - bool TraverseCallExpr(CallExpr *E) { + bool TraverseCallExpr(CallExpr *E) override { if (const auto *DR = dyn_cast(E->getCallee()->IgnoreImplicit()); DR && DR->isImmediateEscalating()) { @@ -2544,13 +2538,13 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { } for (Expr *A : E->arguments()) - if (!getDerived().TraverseStmt(A)) + if (!TraverseStmt(A)) return false; return true; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (const auto *ReferencedFn = dyn_cast(E->getDecl()); ReferencedFn && E->isImmediateEscalating()) { Diag(E, ReferencedFn, /*IsCall=*/false); @@ -2560,7 +2554,7 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { return true; } - bool VisitCXXConstructExpr(CXXConstructExpr *E) { + bool VisitCXXConstructExpr(CXXConstructExpr *E) override { CXXConstructorDecl *D = E->getConstructor(); if (E->isImmediateEscalating()) { Diag(E, D, /*IsCall=*/true); @@ -2569,18 +2563,18 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { return true; } - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { llvm::SaveAndRestore RAII(CurrentInit, Init); - return Base::TraverseConstructorInitializer(Init); + return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init); } - bool TraverseCXXConstructorDecl(CXXConstructorDecl *Ctr) { + bool TraverseCXXConstructorDecl(CXXConstructorDecl *Ctr) override { llvm::SaveAndRestore RAII(CurrentConstructor, Ctr); - return Base::TraverseCXXConstructorDecl(Ctr); + return DynamicRecursiveASTVisitor::TraverseCXXConstructorDecl(Ctr); } - bool TraverseType(QualType T) { return true; } - bool VisitBlockExpr(BlockExpr *T) { return true; } + bool TraverseType(QualType T) override { return true; } + bool VisitBlockExpr(BlockExpr *T) override { return true; } } Visitor(*this, FD); Visitor.TraverseDecl(FD); @@ -18342,7 +18336,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, // The new class type must have the same or less qualifiers as the old type. - if (!OldClassTy.isAtLeastAsQualifiedAs(NewClassTy)) { + if (!OldClassTy.isAtLeastAsQualifiedAs(NewClassTy, getASTContext())) { Diag(New->getLocation(), diag::err_covariant_return_type_class_type_not_same_or_less_qualified) << New->getDeclName() << NewTy << OldTy @@ -18760,18 +18754,18 @@ void Sema::CheckDelegatingCtorCycles() { namespace { /// AST visitor that finds references to the 'this' expression. - class FindCXXThisExpr : public RecursiveASTVisitor { - Sema &S; +class FindCXXThisExpr : public DynamicRecursiveASTVisitor { + Sema &S; - public: - explicit FindCXXThisExpr(Sema &S) : S(S) { } +public: + explicit FindCXXThisExpr(Sema &S) : S(S) {} - bool VisitCXXThisExpr(CXXThisExpr *E) { - S.Diag(E->getLocation(), diag::err_this_static_member_func) + bool VisitCXXThisExpr(CXXThisExpr *E) override { + S.Diag(E->getLocation(), diag::err_this_static_member_func) << E->isImplicit(); - return false; - } - }; + return false; + } +}; } bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 431f267fd5be5c194f4cf309755b75a4bffdcebf..ad1a02cf098b1ef19339386c755c7306b40fbb8f 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -15,9 +15,9 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" @@ -26,7 +26,6 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" @@ -5317,8 +5316,7 @@ SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, namespace { /// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property /// accessor references the backing ivar. -class UnusedBackingIvarChecker - : public RecursiveASTVisitor { +class UnusedBackingIvarChecker : public DynamicRecursiveASTVisitor { public: Sema &S; const ObjCMethodDecl *Method; @@ -5333,7 +5331,7 @@ public: assert(IvarD); } - bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { + bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override { if (E->getDecl() == IvarD) { AccessedIvar = true; return false; @@ -5341,7 +5339,7 @@ public: return true; } - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { if (E->getReceiverKind() == ObjCMessageExpr::Instance && S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) { InvokedSelfMethod = true; diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 9535432052b4b179317e09eacac1f0e440dc1c08..6c89b3e6563da778e0a59e32a9c60fd2d6e7e939 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" @@ -19,8 +18,8 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" #include namespace clang { @@ -717,9 +716,9 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { Qualifiers EQuals, HQuals; ExceptionType = Context.getUnqualifiedArrayType( ExceptionType->getPointeeType(), EQuals); - HandlerType = Context.getUnqualifiedArrayType( - HandlerType->getPointeeType(), HQuals); - if (!HQuals.compatiblyIncludes(EQuals)) + HandlerType = + Context.getUnqualifiedArrayType(HandlerType->getPointeeType(), HQuals); + if (!HQuals.compatiblyIncludes(EQuals, getASTContext())) return false; if (HandlerType->isVoidType() && ExceptionType->isObjectType()) @@ -1406,6 +1405,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { // Most statements can throw if any substatement can throw. case Stmt::OpenACCComputeConstructClass: case Stmt::OpenACCLoopConstructClass: + case Stmt::OpenACCCombinedConstructClass: case Stmt::AttributedStmtClass: case Stmt::BreakStmtClass: case Stmt::CapturedStmtClass: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b9e8b20c1a1a37ca66178379dad7486592aab9eb..2add6b94828ec5b88e541fc3754dfd28bbc744a8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -21,15 +21,13 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/OperationKinds.h" -#include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" @@ -63,7 +61,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/TimeProfiler.h" @@ -5422,32 +5419,33 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, return false; } -struct ImmediateCallVisitor : public RecursiveASTVisitor { +struct ImmediateCallVisitor : DynamicRecursiveASTVisitor { const ASTContext &Context; - ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) {} + ImmediateCallVisitor(const ASTContext &Ctx) : Context(Ctx) { + ShouldVisitImplicitCode = true; + } bool HasImmediateCalls = false; - bool shouldVisitImplicitCode() const { return true; } - bool VisitCallExpr(CallExpr *E) { + bool VisitCallExpr(CallExpr *E) override { if (const FunctionDecl *FD = E->getDirectCallee()) HasImmediateCalls |= FD->isImmediateFunction(); - return RecursiveASTVisitor::VisitStmt(E); + return DynamicRecursiveASTVisitor::VisitStmt(E); } - bool VisitCXXConstructExpr(CXXConstructExpr *E) { + bool VisitCXXConstructExpr(CXXConstructExpr *E) override { if (const FunctionDecl *FD = E->getConstructor()) HasImmediateCalls |= FD->isImmediateFunction(); - return RecursiveASTVisitor::VisitStmt(E); + return DynamicRecursiveASTVisitor::VisitStmt(E); } // SourceLocExpr are not immediate invocations // but CXXDefaultInitExpr/CXXDefaultArgExpr containing a SourceLocExpr // need to be rebuilt so that they refer to the correct SourceLocation and // DeclContext. - bool VisitSourceLocExpr(SourceLocExpr *E) { + bool VisitSourceLocExpr(SourceLocExpr *E) override { HasImmediateCalls = true; - return RecursiveASTVisitor::VisitStmt(E); + return DynamicRecursiveASTVisitor::VisitStmt(E); } // A nested lambda might have parameters with immediate invocations @@ -5456,15 +5454,15 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor { // subexpression). // FIXME: We should consider visiting and transforming captures // with init expressions. - bool VisitLambdaExpr(LambdaExpr *E) { + bool VisitLambdaExpr(LambdaExpr *E) override { return VisitCXXMethodDecl(E->getCallOperator()); } - bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) override { return TraverseStmt(E->getExpr()); } - bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { + bool VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) override { return TraverseStmt(E->getExpr()); } }; @@ -8062,9 +8060,9 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address // spaces is disallowed. - if (lhQual.isAddressSpaceSupersetOf(rhQual)) + if (lhQual.isAddressSpaceSupersetOf(rhQual, S.getASTContext())) ResultAddrSpace = LAddrSpace; - else if (rhQual.isAddressSpaceSupersetOf(lhQual)) + else if (rhQual.isAddressSpaceSupersetOf(lhQual, S.getASTContext())) ResultAddrSpace = RAddrSpace; else { S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) @@ -8976,17 +8974,17 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType, rhq.removeObjCLifetime(); } - if (!lhq.compatiblyIncludes(rhq)) { + if (!lhq.compatiblyIncludes(rhq, S.getASTContext())) { // Treat address-space mismatches as fatal. - if (!lhq.isAddressSpaceSupersetOf(rhq)) + if (!lhq.isAddressSpaceSupersetOf(rhq, S.getASTContext())) return Sema::IncompatiblePointerDiscardsQualifiers; // It's okay to add or remove GC or lifetime qualifiers when converting to // and from void*. - else if (lhq.withoutObjCGCAttr().withoutObjCLifetime() - .compatiblyIncludes( - rhq.withoutObjCGCAttr().withoutObjCLifetime()) - && (lhptee->isVoidType() || rhptee->isVoidType())) + else if (lhq.withoutObjCGCAttr().withoutObjCLifetime().compatiblyIncludes( + rhq.withoutObjCGCAttr().withoutObjCLifetime(), + S.getASTContext()) && + (lhptee->isVoidType() || rhptee->isVoidType())) ; // keep old // Treat lifetime mismatches as fatal. @@ -9173,7 +9171,7 @@ checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType, QualType lhptee = LHSType->castAs()->getPointeeType(); QualType rhptee = RHSType->castAs()->getPointeeType(); - if (!lhptee.isAtLeastAsQualifiedAs(rhptee) && + if (!lhptee.isAtLeastAsQualifiedAs(rhptee, S.getASTContext()) && // make an exception for id

!LHSType->isObjCQualifiedIdType()) return Sema::CompatiblePointerDiscardsQualifiers; @@ -9238,17 +9236,17 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // __builtin_counted_by_ref cannot be assigned to a variable, used in // function call, or in a return. auto FindBuiltinCountedByRefExpr = [&](Expr *E) -> CallExpr * { - struct BuiltinCountedByRefVisitor - : public RecursiveASTVisitor { + struct BuiltinCountedByRefVisitor : DynamicRecursiveASTVisitor { CallExpr *TheCall = nullptr; - bool VisitCallExpr(CallExpr *CE) { + bool VisitCallExpr(CallExpr *CE) override { if (CE->getBuiltinCallee() == Builtin::BI__builtin_counted_by_ref) { TheCall = CE; return false; } return true; } - bool VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE) { + bool + VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE) override { // A UnaryExprOrTypeTraitExpr---e.g. sizeof, __alignof, etc.---isn't // the same as a CallExpr, so if we find a __builtin_counted_by_ref() // call in one, ignore it. @@ -10875,7 +10873,8 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc, // if both are pointers check if operation is valid wrt address spaces if (isLHSPointer && isRHSPointer) { - if (!LHSPointeeTy.isAddressSpaceOverlapping(RHSPointeeTy)) { + if (!LHSPointeeTy.isAddressSpaceOverlapping(RHSPointeeTy, + S.getASTContext())) { S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) << LHSExpr->getType() << RHSExpr->getType() << 1 /*arithmetic op*/ @@ -12406,7 +12405,8 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if (LCanPointeeTy != RCanPointeeTy) { // Treat NULL constant as a special case in OpenCL. if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) { - if (!LCanPointeeTy.isAddressSpaceOverlapping(RCanPointeeTy)) { + if (!LCanPointeeTy.isAddressSpaceOverlapping(RCanPointeeTy, + getASTContext())) { Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) << LHSType << RHSType << 0 /* comparison */ @@ -13824,13 +13824,12 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // subscript on the LHS. int DiagOption = -1; auto FindInvalidUseOfBoundsSafetyCounter = [&](Expr *E) -> CallExpr * { - struct BuiltinCountedByRefVisitor - : public RecursiveASTVisitor { + struct BuiltinCountedByRefVisitor : DynamicRecursiveASTVisitor { CallExpr *CE = nullptr; bool InvalidUse = false; int Option = -1; - bool VisitCallExpr(CallExpr *E) { + bool VisitCallExpr(CallExpr *E) override { if (E->getBuiltinCallee() == Builtin::BI__builtin_counted_by_ref) { CE = E; return false; @@ -13838,12 +13837,12 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, return true; } - bool VisitArraySubscriptExpr(ArraySubscriptExpr *E) { + bool VisitArraySubscriptExpr(ArraySubscriptExpr *E) override { InvalidUse = true; Option = 0; // report 'array expression' in diagnostic. return true; } - bool VisitBinaryOperator(BinaryOperator *E) { + bool VisitBinaryOperator(BinaryOperator *E) override { InvalidUse = true; Option = 1; // report 'binary expression' in diagnostic. return true; @@ -13864,7 +13863,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, CheckForNullPointerDereference(*this, LHSExpr); AssignedEntity AE{LHSExpr}; - checkExprLifetime(*this, AE, RHS.get()); + checkAssignmentLifetime(*this, AE, RHS.get()); if (getLangOpts().CPlusPlus20 && LHSType.isVolatileQualified()) { if (CompoundType.isNull()) { @@ -17793,10 +17792,10 @@ HandleImmediateInvocations(Sema &SemaRef, RemoveNestedImmediateInvocation(SemaRef, Rec, It); } else if (Rec.ImmediateInvocationCandidates.size() == 1 && Rec.ReferenceToConsteval.size()) { - struct SimpleRemove : RecursiveASTVisitor { + struct SimpleRemove : DynamicRecursiveASTVisitor { llvm::SmallPtrSetImpl &DRSet; SimpleRemove(llvm::SmallPtrSetImpl &S) : DRSet(S) {} - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { DRSet.erase(E); return DRSet.size(); } @@ -20105,17 +20104,15 @@ namespace { // TreeTransforms rebuilding the type in a new context. Rather than // duplicating the TreeTransform logic, we should consider reusing it here. // Currently that causes problems when rebuilding LambdaExprs. - class MarkReferencedDecls : public RecursiveASTVisitor { - Sema &S; - SourceLocation Loc; - - public: - typedef RecursiveASTVisitor Inherited; +class MarkReferencedDecls : public DynamicRecursiveASTVisitor { + Sema &S; + SourceLocation Loc; - MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } +public: + MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) {} - bool TraverseTemplateArgument(const TemplateArgument &Arg); - }; + bool TraverseTemplateArgument(const TemplateArgument &Arg) override; +}; } bool MarkReferencedDecls::TraverseTemplateArgument( @@ -20132,7 +20129,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument( } } - return Inherited::TraverseTemplateArgument(Arg); + return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg); } void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index ab9367f911cc51b288c64bcca10e7d961f720d9f..616481d62de887cc7cc0c3ad98571d1bdf1d112e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -18,10 +18,10 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/AlignedAllocation.h" @@ -4783,7 +4783,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType->castAs()->getPointeeType().getAddressSpace(); LangAS AddrSpaceR = FromType->castAs()->getPointeeType().getAddressSpace(); - assert(Qualifiers::isAddressSpaceSupersetOf(AddrSpaceL, AddrSpaceR) && + assert(Qualifiers::isAddressSpaceSupersetOf(AddrSpaceL, AddrSpaceR, + getASTContext()) && "Invalid cast"); CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; @@ -6641,7 +6642,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, // same type as, or a base class of, the class of T1, and // [cv2 > cv1]. if (FRec == TRec || FDerivedFromT) { - if (TTy.isAtLeastAsQualifiedAs(FTy)) { + if (TTy.isAtLeastAsQualifiedAs(FTy, Self.getASTContext())) { InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy); InitializationSequence InitSeq(Self, Entity, Kind, From); if (InitSeq) { @@ -7363,8 +7364,8 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, if (Q1.getAddressSpace() == Q2.getAddressSpace()) { Quals.setAddressSpace(Q1.getAddressSpace()); } else if (Steps.size() == 1) { - bool MaybeQ1 = Q1.isAddressSpaceSupersetOf(Q2); - bool MaybeQ2 = Q2.isAddressSpaceSupersetOf(Q1); + bool MaybeQ1 = Q1.isAddressSpaceSupersetOf(Q2, getASTContext()); + bool MaybeQ2 = Q2.isAddressSpaceSupersetOf(Q1, getASTContext()); if (MaybeQ1 == MaybeQ2) { // Exception for ptr size address spaces. Should be able to choose // either address space during comparison. @@ -8821,13 +8822,13 @@ static ExprResult attemptRecovery(Sema &SemaRef, } namespace { -class FindTypoExprs : public RecursiveASTVisitor { +class FindTypoExprs : public DynamicRecursiveASTVisitor { llvm::SmallSetVector &TypoExprs; public: explicit FindTypoExprs(llvm::SmallSetVector &TypoExprs) : TypoExprs(TypoExprs) {} - bool VisitTypoExpr(TypoExpr *TE) { + bool VisitTypoExpr(TypoExpr *TE) override { TypoExprs.insert(TE); return true; } diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index f1ba26f38520a93f9b2e500a54fcb0bd4d00533d..c32df6076928134c3d2b319c6aa3a50acfdeb542 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -9,7 +9,6 @@ // This file implements semantic analysis member access expressions. // //===----------------------------------------------------------------------===// -#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -20,7 +19,6 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 3fcbbb417ff1faa40aef43c713b6ea49096a0a5e..18d9d38eee92fad1299c0d36292e0887999afc88 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -26,9 +26,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" -#include "llvm/ADT/SmallString.h" #include "llvm/Support/ConvertUTF.h" #include diff --git a/clang/lib/Sema/SemaFixItUtils.cpp b/clang/lib/Sema/SemaFixItUtils.cpp index 2c85a53194301f457488869cf9cac71698866dbd..1dad46fd6b9401caa1b6c4bd3431f1bd41b31736 100644 --- a/clang/lib/Sema/SemaFixItUtils.cpp +++ b/clang/lib/Sema/SemaFixItUtils.cpp @@ -24,7 +24,7 @@ bool ConversionFixItGenerator::compareTypesSimple(CanQualType From, Sema &S, SourceLocation Loc, ExprValueKind FromVK) { - if (!To.isAtLeastAsQualifiedAs(From)) + if (!To.isAtLeastAsQualifiedAs(From, S.getASTContext())) return false; From = From.getNonReferenceType(); @@ -41,8 +41,8 @@ bool ConversionFixItGenerator::compareTypesSimple(CanQualType From, const CanQualType FromUnq = From.getUnqualifiedType(); const CanQualType ToUnq = To.getUnqualifiedType(); - if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq)) ) && - To.isAtLeastAsQualifiedAs(From)) + if ((FromUnq == ToUnq || (S.IsDerivedFrom(Loc, FromUnq, ToUnq))) && + To.isAtLeastAsQualifiedAs(From, S.getASTContext())) return true; return false; } diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index a76a0a412768961aace6531647fe5200013481aa..6fe4d2353a2282a1aa90152f04ff04ac95bdc3b7 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -12,8 +12,10 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtObjC.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceManager.h" #include "clang/Sema/SemaInternal.h" @@ -805,7 +807,8 @@ private: auto MaybeAddTemplateNote = [&](const Decl *D) { if (const FunctionDecl *FD = dyn_cast(D)) { - while (FD != nullptr && FD->isTemplateInstantiation()) { + while (FD != nullptr && FD->isTemplateInstantiation() && + FD->getPointOfInstantiation().isValid()) { S.Diag(FD->getPointOfInstantiation(), diag::note_func_effect_from_template); FD = FD->getTemplateInstantiationPattern(); @@ -964,9 +967,7 @@ private: // being checked for implicit conformance. // // Violations are always routed to a PendingFunctionAnalysis. - struct FunctionBodyASTVisitor : RecursiveASTVisitor { - using Base = RecursiveASTVisitor; - + struct FunctionBodyASTVisitor : DynamicRecursiveASTVisitor { Analyzer &Outer; PendingFunctionAnalysis &CurrentFunction; CallableInfo &CurrentCaller; @@ -978,7 +979,10 @@ private: PendingFunctionAnalysis &CurrentFunction, CallableInfo &CurrentCaller) : Outer(Outer), CurrentFunction(CurrentFunction), - CurrentCaller(CurrentCaller) {} + CurrentCaller(CurrentCaller) { + ShouldVisitImplicitCode = true; + ShouldWalkTypesOfTypeLocs = false; + } // -- Entry point -- void run() { @@ -1119,53 +1123,49 @@ private: // -- Methods for use of RecursiveASTVisitor -- - bool shouldVisitImplicitCode() const { return true; } - - bool shouldWalkTypesOfTypeLocs() const { return false; } - - bool VisitCXXThrowExpr(CXXThrowExpr *Throw) { + bool VisitCXXThrowExpr(CXXThrowExpr *Throw) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow, ViolationID::ThrowsOrCatchesExceptions, Throw->getThrowLoc()); return true; } - bool VisitCXXCatchStmt(CXXCatchStmt *Catch) { + bool VisitCXXCatchStmt(CXXCatchStmt *Catch) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch, ViolationID::ThrowsOrCatchesExceptions, Catch->getCatchLoc()); return true; } - bool VisitObjCAtThrowStmt(ObjCAtThrowStmt *Throw) { + bool VisitObjCAtThrowStmt(ObjCAtThrowStmt *Throw) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeThrow, ViolationID::ThrowsOrCatchesExceptions, Throw->getThrowLoc()); return true; } - bool VisitObjCAtCatchStmt(ObjCAtCatchStmt *Catch) { + bool VisitObjCAtCatchStmt(ObjCAtCatchStmt *Catch) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch, ViolationID::ThrowsOrCatchesExceptions, Catch->getAtCatchLoc()); return true; } - bool VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Finally) { + bool VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *Finally) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch, ViolationID::ThrowsOrCatchesExceptions, Finally->getAtFinallyLoc()); return true; } - bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) { + bool VisitObjCMessageExpr(ObjCMessageExpr *Msg) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeObjCMessageSend, ViolationID::AccessesObjCMethodOrProperty, Msg->getBeginLoc()); return true; } - bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *ARP) { + bool VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *ARP) override { // Under the hood, @autorelease (potentially?) allocates memory and // invokes ObjC methods. We don't currently have memory allocation as // a "language construct" but we do have ObjC messaging, so diagnose that. @@ -1175,7 +1175,7 @@ private: return true; } - bool VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Sync) { + bool VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Sync) override { // Under the hood, this calls objc_sync_enter and objc_sync_exit, wrapped // in a @try/@finally block. Diagnose this generically as "ObjC // messaging". @@ -1185,14 +1185,14 @@ private: return true; } - bool VisitSEHExceptStmt(SEHExceptStmt *Exc) { + bool VisitSEHExceptStmt(SEHExceptStmt *Exc) override { diagnoseLanguageConstruct(FunctionEffect::FE_ExcludeCatch, ViolationID::ThrowsOrCatchesExceptions, Exc->getExceptLoc()); return true; } - bool VisitCallExpr(CallExpr *Call) { + bool VisitCallExpr(CallExpr *Call) override { LLVM_DEBUG(llvm::dbgs() << "VisitCallExpr : " << Call->getBeginLoc().printToString(Outer.S.SourceMgr) @@ -1216,7 +1216,7 @@ private: return true; } - bool VisitVarDecl(VarDecl *Var) { + bool VisitVarDecl(VarDecl *Var) override { LLVM_DEBUG(llvm::dbgs() << "VisitVarDecl : " << Var->getBeginLoc().printToString(Outer.S.SourceMgr) @@ -1234,7 +1234,7 @@ private: return true; } - bool VisitCXXNewExpr(CXXNewExpr *New) { + bool VisitCXXNewExpr(CXXNewExpr *New) override { // RecursiveASTVisitor does not visit the implicit call to operator new. if (FunctionDecl *FD = New->getOperatorNew()) { CallableInfo CI(*FD, SpecialFuncType::OperatorNew); @@ -1249,7 +1249,7 @@ private: return true; } - bool VisitCXXDeleteExpr(CXXDeleteExpr *Delete) { + bool VisitCXXDeleteExpr(CXXDeleteExpr *Delete) override { // RecursiveASTVisitor does not visit the implicit call to operator // delete. if (FunctionDecl *FD = Delete->getOperatorDelete()) { @@ -1262,7 +1262,7 @@ private: return true; } - bool VisitCXXConstructExpr(CXXConstructExpr *Construct) { + bool VisitCXXConstructExpr(CXXConstructExpr *Construct) override { LLVM_DEBUG(llvm::dbgs() << "VisitCXXConstructExpr : " << Construct->getBeginLoc().printToString( Outer.S.SourceMgr) @@ -1277,28 +1277,28 @@ private: return true; } - bool TraverseStmt(Stmt *Statement) { + bool TraverseStmt(Stmt *Statement) override { // If this statement is a `requires` clause from the top-level function // being traversed, ignore it, since it's not generating runtime code. // We skip the traversal of lambdas (beyond their captures, see // TraverseLambdaExpr below), so just caching this from our constructor // should suffice. - // The exact same is true for a conditional `noexcept()` clause. if (Statement != TrailingRequiresClause && Statement != NoexceptExpr) - return Base::TraverseStmt(Statement); + return DynamicRecursiveASTVisitor::TraverseStmt(Statement); return true; } - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { ViolationSite PrevVS = VSite; if (Init->isAnyMemberInitializer()) VSite.setKind(ViolationSite::Kind::MemberInitializer); - bool Result = Base::TraverseConstructorInitializer(Init); + bool Result = + DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init); VSite = PrevVS; return Result; } - bool TraverseCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + bool TraverseCXXDefaultArgExpr(CXXDefaultArgExpr *E) override { LLVM_DEBUG(llvm::dbgs() << "TraverseCXXDefaultArgExpr : " << E->getUsedLocation().printToString(Outer.S.SourceMgr) @@ -1308,12 +1308,12 @@ private: if (VSite.kind() == ViolationSite::Kind::Default) VSite = ViolationSite{E}; - bool Result = Base::TraverseCXXDefaultArgExpr(E); + bool Result = DynamicRecursiveASTVisitor::TraverseCXXDefaultArgExpr(E); VSite = PrevVS; return Result; } - bool TraverseLambdaExpr(LambdaExpr *Lambda) { + bool TraverseLambdaExpr(LambdaExpr *Lambda) override { // We override this so as to be able to skip traversal of the lambda's // body. We have to explicitly traverse the captures. Why not return // false from shouldVisitLambdaBody()? Because we need to visit a lambda's @@ -1326,13 +1326,13 @@ private: return true; } - bool TraverseBlockExpr(BlockExpr * /*unused*/) { + bool TraverseBlockExpr(BlockExpr * /*unused*/) override { // As with lambdas, don't traverse the block's body. // TODO: are the capture expressions (ctor call?) safe? return true; } - bool VisitDeclRefExpr(const DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { const ValueDecl *Val = E->getDecl(); if (const auto *Var = dyn_cast(Val)) { if (Var->getTLSKind() != VarDecl::TLS_None) { @@ -1346,23 +1346,30 @@ private: return true; } - bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) { + bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) override { return TraverseStmt(Node->getResultExpr()); } - bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { + bool + TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) override { return true; } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) { return true; } + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override { + return true; + } - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) { return true; } + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { return true; } - bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) { return true; } + bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override { + return true; + } - bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) { return true; } + bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) override { return true; } // Skip concept requirements since they don't generate code. - bool TraverseConceptRequirement(concepts::Requirement *R) { return true; } + bool TraverseConceptRequirement(concepts::Requirement *R) override { + return true; + } }; }; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 65b0d9cd65637f47cf81bc5494192c85ff9f69b6..f4fc0f2ddc27a69116ef4cec41e9ceef3618a6e5 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -15,8 +15,8 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" @@ -1304,9 +1304,7 @@ namespace { /// and of all exported functions, and any functions that are referenced /// from this AST. In other words, any functions that are reachable from /// the entry points. -class DiagnoseHLSLAvailability - : public RecursiveASTVisitor { - +class DiagnoseHLSLAvailability : public DynamicRecursiveASTVisitor { Sema &SemaRef; // Stack of functions to be scaned @@ -1409,14 +1407,14 @@ public: void RunOnTranslationUnit(const TranslationUnitDecl *TU); void RunOnFunction(const FunctionDecl *FD); - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { FunctionDecl *FD = llvm::dyn_cast(DRE->getDecl()); if (FD) HandleFunctionOrMethodRef(FD, DRE); return true; } - bool VisitMemberExpr(MemberExpr *ME) { + bool VisitMemberExpr(MemberExpr *ME) override { FunctionDecl *FD = llvm::dyn_cast(ME->getMemberDecl()); if (FD) HandleFunctionOrMethodRef(FD, ME); @@ -2135,6 +2133,14 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_elementwise_clip: { + if (SemaRef.checkArgCount(TheCall, 1)) + return true; + + if (CheckScalarOrVector(&SemaRef, TheCall, SemaRef.Context.FloatTy, 0)) + return true; + break; + } case Builtin::BI__builtin_elementwise_acos: case Builtin::BI__builtin_elementwise_asin: case Builtin::BI__builtin_elementwise_atan: @@ -2225,47 +2231,40 @@ static void BuildFlattenedTypeList(QualType BaseTy, } bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) { - if (QT.isNull()) + // null and array types are not allowed. + if (QT.isNull() || QT->isArrayType()) return false; - // check if the outer type was an array type - if (QT->isArrayType()) + // UDT types are not allowed + if (QT->isRecordType()) return false; - llvm::SmallVector QTTypes; - BuildFlattenedTypeList(QT, QTTypes); - - assert(QTTypes.size() > 0 && - "expected at least one constituent type from non-null type"); - QualType FirstQT = SemaRef.Context.getCanonicalType(QTTypes[0]); - - // element count cannot exceed 4 - if (QTTypes.size() > 4) + if (QT->isBooleanType() || QT->isEnumeralType()) return false; - for (QualType TempQT : QTTypes) { - // ensure homogeneity - if (!getASTContext().hasSameUnqualifiedType(FirstQT, TempQT)) + // the only other valid builtin types are scalars or vectors + if (QT->isArithmeticType()) { + if (SemaRef.Context.getTypeSize(QT) / 8 > 16) return false; + return true; } - if (const BuiltinType *BT = FirstQT->getAs()) { - if (BT->isBooleanType() || BT->isEnumeralType()) + if (const VectorType *VT = QT->getAs()) { + int ArraySize = VT->getNumElements(); + + if (ArraySize > 4) return false; - // Check if it is an array type. - if (FirstQT->isArrayType()) + QualType ElTy = VT->getElementType(); + if (ElTy->isBooleanType()) return false; - } - // if the loop above completes without returning, then - // we've guaranteed homogeneity - int TotalSizeInBytes = - (SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size(); - if (TotalSizeInBytes > 16) - return false; + if (SemaRef.Context.getTypeSize(QT) / 8 > 16) + return false; + return true; + } - return true; + return false; } bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index f13355bb93cbebcea92f81b1bc26e442dcc41e60..7c03a12e812809cf69b40fdd7fc4c6037faa998e 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -16,10 +16,8 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/ExprOpenMP.h" #include "clang/AST/IgnoreExpr.h" #include "clang/AST/TypeLoc.h" -#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" @@ -28,13 +26,11 @@ #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Ownership.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLForwardCompat.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" @@ -4718,7 +4714,7 @@ static void TryReferenceListInitialization(Sema &S, if (T1Quals.hasAddressSpace()) { Qualifiers T2Quals; (void)S.Context.getUnqualifiedArrayType(InitList->getType(), T2Quals); - if (!T1Quals.isAddressSpaceSupersetOf(T2Quals)) { + if (!T1Quals.isAddressSpaceSupersetOf(T2Quals, S.getASTContext())) { Sequence.SetFailed( InitializationSequence::FK_ReferenceInitDropsQualifiers); return; @@ -5324,8 +5320,9 @@ static void TryReferenceInitializationCore(Sema &S, // shall be an rvalue reference. // For address spaces, we interpret this to mean that an addr space // of a reference "cv1 T1" is a superset of addr space of "cv2 T2". - if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() && - T1Quals.isAddressSpaceSupersetOf(T2Quals))) { + if (isLValueRef && + !(T1Quals.hasConst() && !T1Quals.hasVolatile() && + T1Quals.isAddressSpaceSupersetOf(T2Quals, S.getASTContext()))) { if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) @@ -5334,7 +5331,7 @@ static void TryReferenceInitializationCore(Sema &S, ConvOvlResult); else if (!InitCategory.isLValue()) Sequence.SetFailed( - T1Quals.isAddressSpaceSupersetOf(T2Quals) + T1Quals.isAddressSpaceSupersetOf(T2Quals, S.getASTContext()) ? InitializationSequence:: FK_NonConstLValueReferenceBindingToTemporary : InitializationSequence::FK_ReferenceInitDropsQualifiers); @@ -5519,7 +5516,7 @@ static void TryReferenceInitializationCore(Sema &S, unsigned T2CVRQuals = T2Quals.getCVRQualifiers(); if (RefRelationship == Sema::Ref_Related && ((T1CVRQuals | T2CVRQuals) != T1CVRQuals || - !T1Quals.isAddressSpaceSupersetOf(T2Quals))) { + !T1Quals.isAddressSpaceSupersetOf(T2Quals, S.getASTContext()))) { Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); return; } @@ -5536,8 +5533,8 @@ static void TryReferenceInitializationCore(Sema &S, Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*BindingTemporary=*/true); if (T1Quals.hasAddressSpace()) { - if (!Qualifiers::isAddressSpaceSupersetOf(T1Quals.getAddressSpace(), - LangAS::Default)) { + if (!Qualifiers::isAddressSpaceSupersetOf( + T1Quals.getAddressSpace(), LangAS::Default, S.getASTContext())) { Sequence.SetFailed( InitializationSequence::FK_ReferenceAddrspaceMismatchTemporary); return; @@ -7404,7 +7401,7 @@ PerformConstructorInitialization(Sema &S, void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { - return sema::checkExprLifetime(*this, Entity, Init); + return sema::checkInitLifetime(*this, Entity, Init); } static void DiagnoseNarrowingInInitList(Sema &S, @@ -8629,7 +8626,7 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, !fromDecl->isInvalidDecl() && !destDecl->isInvalidDecl() && !fromDecl->hasDefinition() && destPointeeType.getQualifiers().compatiblyIncludes( - fromPointeeType.getQualifiers())) + fromPointeeType.getQualifiers(), S.getASTContext())) S.Diag(fromDecl->getLocation(), diag::note_forward_class_conversion) << S.getASTContext().getTagDeclType(fromDecl) << S.getASTContext().getTagDeclType(destDecl); @@ -8907,7 +8904,7 @@ bool InitializationSequence::Diagnose(Sema &S, SourceType.getQualifiers() - NonRefType.getQualifiers(); if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf( - SourceType.getQualifiers())) + SourceType.getQualifiers(), S.getASTContext())) S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) << NonRefType << SourceType << 1 /*addr space*/ << Args[0]->getSourceRange(); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index e7afa0f4c81fc4965e8d003142d1065b5cbb244d..a67c0b2b367d1aadc784712414982150f0adb9ec 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1950,8 +1950,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) { LambdaScopeInfo LSI = *cast(FunctionScopes.back()); ActOnFinishFunctionBody(LSI.CallOperator, Body); - maybeAddDeclWithEffects(LSI.CallOperator); - return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI); } @@ -2284,6 +2282,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: break; } + maybeAddDeclWithEffects(LSI->CallOperator); } return MaybeBindToTemporary(Lambda); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 8468e9a730c2d0e3bdd964150f2382a6aa749104..e1171d4284c763ecddc8d73a2c585823797291ae 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -21,7 +21,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleLoader.h" diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index d6ebc382dad472a5e928db68860c580213310314..76589bff40be97cd8876eb9450b7e5e0f433de62 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -17,7 +17,6 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/StringExtras.h" -#include using namespace clang; using namespace sema; diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp index 0359d18dd945251dc3012b51ac5c673457c1df2c..57eda18c2d8e151eb149bf5e017e6b190ed8ebeb 100644 --- a/clang/lib/Sema/SemaObjC.cpp +++ b/clang/lib/Sema/SemaObjC.cpp @@ -1350,7 +1350,7 @@ bool SemaObjC::isObjCWritebackConversion(QualType FromType, QualType ToType, // Make sure that we have compatible qualifiers. FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing); - if (!ToQuals.compatiblyIncludes(FromQuals)) + if (!ToQuals.compatiblyIncludes(FromQuals, getASTContext())) return false; // Remove qualifiers from the pointee type we're converting from; they diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 6cef76fbde1d2596ec97e7b255b8bc1ff598685c..93a17e84598115a0e5adcace9a65d0f9e873d3c2 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -19,10 +19,8 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallString.h" using namespace clang; diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 25427bf2309bf79a0aac0e500fdd50ab038329cc..76be9a2abf5e46b83e200a55e1d67659f22170c0 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -30,6 +30,9 @@ bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K, // Nothing to do here, both invalid and unimplemented don't really need to // do anything. break; + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: case OpenACCDirectiveKind::Parallel: case OpenACCDirectiveKind::Serial: case OpenACCDirectiveKind::Kernels: @@ -431,6 +434,7 @@ bool checkValidAfterDeviceType( // This is only a requirement on compute and loop constructs so far, so this // is fine otherwise. if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind()) && NewClause.getDirectiveKind() != OpenACCDirectiveKind::Loop) return false; @@ -476,10 +480,29 @@ bool checkValidAfterDeviceType( default: break; } + } else if (isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind())) { + // This seems like it should be the union of 2.9 and 2.5.4 from above. + switch (NewClause.getClauseKind()) { + case OpenACCClauseKind::Async: + case OpenACCClauseKind::Wait: + case OpenACCClauseKind::NumGangs: + case OpenACCClauseKind::NumWorkers: + case OpenACCClauseKind::VectorLength: + case OpenACCClauseKind::Collapse: + case OpenACCClauseKind::Gang: + case OpenACCClauseKind::Worker: + case OpenACCClauseKind::Vector: + case OpenACCClauseKind::Seq: + case OpenACCClauseKind::Independent: + case OpenACCClauseKind::Auto: + case OpenACCClauseKind::Tile: + return false; + default: + break; + } } S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type) << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind() - << isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()) << NewClause.getDirectiveKind(); S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here); return true; @@ -505,7 +528,8 @@ class SemaOpenACCClauseVisitor { if (Itr != ExistingClauses.end()) { SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine) - << Clause.getClauseKind() << (*Itr)->getClauseKind(); + << Clause.getClauseKind() << (*Itr)->getClauseKind() + << Clause.getDirectiveKind(); SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); return true; @@ -548,10 +572,12 @@ public: OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + // Restrictions only properly implemented on 'compute'/'combined' constructs, + // and 'compute'/'combined' constructs are the only construct that can do + // anything with this yet, so skip/treat as unimplemented in this case. + // Only 'data' is left. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // Don't add an invalid clause to the AST. @@ -572,6 +598,7 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause( SemaOpenACC::OpenACCParsedClause &Clause) { + // TODO OpenACC: Remove this when we get combined construct impl for this. if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) return isNotImplemented(); @@ -602,10 +629,11 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + // Restrictions only properly implemented on 'compute'/'combined' constructs, + // and 'compute'/'combined' constructs are the only construct that can do + // anything with this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // There is no prose in the standard that says duplicates aren't allowed, @@ -638,7 +666,8 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause( // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // TODO OpenACC: When we implement this for 'update', this takes a @@ -671,6 +700,8 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause( // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with // this yet, so skip/treat as unimplemented in this case. + // TODO OpenACC: Remove this check when we have combined constructs for this + // clause. if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); @@ -726,6 +757,7 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause( // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with // this yet, so skip/treat as unimplemented in this case. + // TODO: OpenACC: Remove when we get combined constructs. if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); @@ -747,6 +779,7 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause( // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with // this yet, so skip/treat as unimplemented in this case. + // TODO: OpenACC: Remove when we get combined constructs. if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); @@ -765,10 +798,11 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) + // Restrictions only properly implemented on 'compute'/'combined' constructs, + // and 'compute'/'combined' constructs are the only construct that can do + // anything with this yet, so skip/treat as unimplemented in this case. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // There is no prose in the standard that says duplicates aren't allowed, @@ -787,14 +821,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' and 'loop' - // constructs, and 'compute'/'loop' constructs are the only construct that - // can do anything with this yet, so skip/treat as unimplemented in this - // case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && - Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) - return isNotImplemented(); - // ActOnVar ensured that everything is a valid variable reference, so there // really isn't anything to do here. GCC does some duplicate-finding, though // it isn't apparent in the standard where this is justified. @@ -806,12 +832,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' constructs, and - // 'compute' constructs are the only construct that can do anything with - // this yet, so skip/treat as unimplemented in this case. - if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind())) - return isNotImplemented(); - // ActOnVar ensured that everything is a valid variable reference, so there // really isn't anything to do here. GCC does some duplicate-finding, though // it isn't apparent in the standard where this is justified. @@ -975,12 +995,13 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'compute' and 'loop' - // constructs, and 'compute'/'loop' constructs are the only construct that - // can do anything with this yet, so skip/treat as unimplemented in this - // case. + // Restrictions only properly implemented on 'compute', 'combined', and + // 'loop' constructs, and 'compute'/'combined'/'loop' constructs are the only + // construct that can do anything with this yet, so skip/treat as + // unimplemented in this case. if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && - Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) + Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop && + !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) return isNotImplemented(); // TODO OpenACC: Once we get enough of the CodeGen implemented that we have @@ -994,12 +1015,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'loop' constructs, and it is - // the only construct that can do anything with this, so skip/treat as - // unimplemented for the combined constructs. - if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) - return isNotImplemented(); - // OpenACC 3.3 2.9: // Only one of the seq, independent, and auto clauses may appear. const auto *Itr = @@ -1018,12 +1033,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'loop' constructs, and it is - // the only construct that can do anything with this, so skip/treat as - // unimplemented for the combined constructs. - if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) - return isNotImplemented(); - // OpenACC 3.3 2.9: // Only one of the seq, independent, and auto clauses may appear. const auto *Itr = llvm::find_if( @@ -1353,10 +1362,10 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause( SemaOpenACC::OpenACCParsedClause &Clause) { - // Restrictions only properly implemented on 'loop' constructs, and it is - // the only construct that can do anything with this, so skip/treat as - // unimplemented for the combined constructs. - if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) + // Restrictions only properly implemented on 'loop' constructs and combined , + // and it is the only construct that can do anything with this, so skip/treat + // as unimplemented for the routine constructs. + if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Routine) return isNotImplemented(); // OpenACC 3.3 2.9: @@ -1380,14 +1389,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause( if (Itr != ExistingClauses.end()) { SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine) - << Clause.getClauseKind() << (*Itr)->getClauseKind(); + << Clause.getClauseKind() << (*Itr)->getClauseKind() + << Clause.getDirectiveKind(); SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); return nullptr; } - // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some - // restrictions when there is a 'seq' clause in place. We probably need to - // implement that. return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(), Clause.getEndLoc()); } @@ -1397,6 +1404,7 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause( // Restrictions only properly implemented on 'compute' constructs, and // 'compute' constructs are the only construct that can do anything with // this yet, so skip/treat as unimplemented in this case. + // TODO: OpenACC: Remove check once we get combined constructs for this clause. if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) return isNotImplemented(); @@ -1487,6 +1495,10 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause( OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause( SemaOpenACC::OpenACCParsedClause &Clause) { + // TODO: Remove this check once we implement this for combined constructs. + if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) && + Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) + return isNotImplemented(); // Duplicates here are not really sensible. We could possible permit // multiples if they all had the same value, but there isn't really a good // reason to do so. Also, this simplifies the suppression of duplicates, in @@ -1527,7 +1539,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( DirKind(DK), OldLoopGangClauseOnKernelLoc(S.LoopGangClauseOnKernelLoc), OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc), OldLoopVectorClauseLoc(S.LoopVectorClauseLoc), - OldLoopWithoutSeqLoc(S.LoopWithoutSeqLoc), + OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo), ActiveReductionClauses(S.ActiveReductionClauses), LoopRAII(SemaRef, /*PreserveDepth=*/false) { @@ -1548,7 +1560,53 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( SemaRef.LoopGangClauseOnKernelLoc = {}; SemaRef.LoopWorkerClauseLoc = {}; SemaRef.LoopVectorClauseLoc = {}; - SemaRef.LoopWithoutSeqLoc = {}; + SemaRef.LoopWithoutSeqInfo = {}; + } else if (DirKind == OpenACCDirectiveKind::ParallelLoop || + DirKind == OpenACCDirectiveKind::SerialLoop || + DirKind == OpenACCDirectiveKind::KernelsLoop) { + SemaRef.ActiveComputeConstructInfo.Kind = DirKind; + SemaRef.ActiveComputeConstructInfo.Clauses = Clauses; + + CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses); + SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses); + SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses); + + // TODO: OpenACC: We need to set these 3, CollapseInfo, and TileInfo + SemaRef.LoopGangClauseOnKernelLoc = {}; + SemaRef.LoopWorkerClauseLoc = {}; + SemaRef.LoopVectorClauseLoc = {}; + + // Set the active 'loop' location if there isn't a 'seq' on it, so we can + // diagnose the for loops. + SemaRef.LoopWithoutSeqInfo = {}; + if (Clauses.end() == + llvm::find_if(Clauses, llvm::IsaPred)) + SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc}; + + // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels + // construct, the gang clause behaves as follows. ... The region of a loop + // with a gang clause may not contain another loop with a gang clause unless + // within a nested compute region. + // + // We don't bother doing this when this is a template instantiation, as + // there is no reason to do these checks: the existance of a + // gang/kernels/etc cannot be dependent. + if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) { + // This handles the 'outer loop' part of this. + auto *Itr = llvm::find_if(Clauses, llvm::IsaPred); + if (Itr != Clauses.end()) + SemaRef.LoopGangClauseOnKernelLoc = (*Itr)->getBeginLoc(); + } + + if (UnInstClauses.empty()) { + auto *Itr = llvm::find_if(Clauses, llvm::IsaPred); + if (Itr != Clauses.end()) + SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc(); + + auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred); + if (Itr2 != Clauses.end()) + SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc(); + } } else if (DirKind == OpenACCDirectiveKind::Loop) { CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses); SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses); @@ -1556,10 +1614,10 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII( // Set the active 'loop' location if there isn't a 'seq' on it, so we can // diagnose the for loops. - SemaRef.LoopWithoutSeqLoc = {}; + SemaRef.LoopWithoutSeqInfo = {}; if (Clauses.end() == llvm::find_if(Clauses, llvm::IsaPred)) - SemaRef.LoopWithoutSeqLoc = DirLoc; + SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc}; // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels // construct, the gang clause behaves as follows. ... The region of a loop @@ -1661,12 +1719,15 @@ SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() { SemaRef.LoopGangClauseOnKernelLoc = OldLoopGangClauseOnKernelLoc; SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc; SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc; - SemaRef.LoopWithoutSeqLoc = OldLoopWithoutSeqLoc; + SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo; SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses); if (DirKind == OpenACCDirectiveKind::Parallel || DirKind == OpenACCDirectiveKind::Serial || - DirKind == OpenACCDirectiveKind::Kernels) { + DirKind == OpenACCDirectiveKind::Kernels || + DirKind == OpenACCDirectiveKind::ParallelLoop || + DirKind == OpenACCDirectiveKind::SerialLoop || + DirKind == OpenACCDirectiveKind::KernelsLoop) { // Nothing really to do here, the restorations above should be enough for // now. } else if (DirKind == OpenACCDirectiveKind::Loop) { @@ -1875,6 +1936,9 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, case OpenACCDirectiveKind::Parallel: case OpenACCDirectiveKind::Serial: case OpenACCDirectiveKind::Kernels: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: case OpenACCDirectiveKind::Loop: // Nothing to do here, there is no real legalization that needs to happen // here as these constructs do not take any arguments. @@ -2705,7 +2769,7 @@ bool isValidLoopVariableType(QualType LoopVarTy) { } // namespace void SemaOpenACC::ForStmtBeginChecker::check() { - if (!SemaRef.LoopWithoutSeqLoc.isValid()) + if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid) return; if (AlreadyChecked) @@ -2745,9 +2809,10 @@ void SemaOpenACC::ForStmtBeginChecker::check() { QualType VarType = InitVar->getType().getNonReferenceType(); if (!isValidLoopVariableType(VarType)) { SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type) - << VarType; - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + << SemaRef.LoopWithoutSeqInfo.Kind << VarType; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, + diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; } return; } @@ -2764,18 +2829,22 @@ void SemaOpenACC::ForStmtBeginChecker::check() { const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() { if (!Init) { if (InitChanged) { - SemaRef.Diag(ForLoc, diag::err_acc_loop_variable); - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + SemaRef.Diag(ForLoc, diag::err_acc_loop_variable) + << SemaRef.LoopWithoutSeqInfo.Kind; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, + diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; } return nullptr; } auto DiagLoopVar = [&]() { if (InitChanged) { - SemaRef.Diag(Init->getBeginLoc(), diag::err_acc_loop_variable); - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + SemaRef.Diag(Init->getBeginLoc(), diag::err_acc_loop_variable) + << SemaRef.LoopWithoutSeqInfo.Kind; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, + diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; } return nullptr; }; @@ -2840,9 +2909,10 @@ const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() { if (!isValidLoopVariableType(VarType)) { if (InitChanged) { SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type) - << VarType; - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + << SemaRef.LoopWithoutSeqInfo.Kind << VarType; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, + diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; } return nullptr; } @@ -2851,9 +2921,10 @@ const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() { } void SemaOpenACC::ForStmtBeginChecker::checkCond() { if (!*Cond) { - SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition); - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition) + << SemaRef.LoopWithoutSeqInfo.Kind; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; } // Nothing else to do here. we could probably do some additional work to look // into the termination condition, but that error-prone. For now, we don't @@ -2865,15 +2936,17 @@ void SemaOpenACC::ForStmtBeginChecker::checkCond() { void SemaOpenACC::ForStmtBeginChecker::checkInc(const ValueDecl *Init) { if (!*Inc) { - SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic); - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic) + << SemaRef.LoopWithoutSeqInfo.Kind; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; return; } auto DiagIncVar = [this] { - SemaRef.Diag((*Inc)->getBeginLoc(), diag::err_acc_loop_not_monotonic); - SemaRef.Diag(SemaRef.LoopWithoutSeqLoc, diag::note_acc_construct_here) - << "loop"; + SemaRef.Diag((*Inc)->getBeginLoc(), diag::err_acc_loop_not_monotonic) + << SemaRef.LoopWithoutSeqInfo.Kind; + SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here) + << SemaRef.LoopWithoutSeqInfo.Kind; return; }; @@ -3173,6 +3246,13 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr); } + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: { + return OpenACCCombinedConstruct::Create( + getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses, + AssocStmt.isUsable() ? AssocStmt.get() : nullptr); + } case OpenACCDirectiveKind::Loop: { return OpenACCLoopConstruct::Create( getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc, @@ -3202,11 +3282,15 @@ StmtResult SemaOpenACC::ActOnAssociatedStmt( // the 'structured block'. return AssocStmt; case OpenACCDirectiveKind::Loop: + case OpenACCDirectiveKind::ParallelLoop: + case OpenACCDirectiveKind::SerialLoop: + case OpenACCDirectiveKind::KernelsLoop: if (!AssocStmt.isUsable()) return StmtError(); if (!isa(AssocStmt.get())) { - Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop); + Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop) + << K; Diag(DirectiveLoc, diag::note_acc_construct_here) << K; return StmtError(); } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 6525689c952771f8114f98c7de8d4836a46bb752..be9acbbb5af283c3409d4b24f7d684e0c3757fba 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -20,12 +20,11 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclOpenMP.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/OpenMPClause.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/StmtVisitor.h" -#include "clang/AST/TypeOrdering.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PartialDiagnostic.h" @@ -37,7 +36,6 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Sema.h" -#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/ADT/STLExtras.h" @@ -49,7 +47,6 @@ #include "llvm/Frontend/OpenMP/OMPConstants.h" #include "llvm/IR/Assumptions.h" #include -#include using namespace clang; using namespace llvm::omp; @@ -7720,7 +7717,7 @@ struct LoopIterationSpace final { /// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls /// set are referenced. Used for verifying loop nest structure before /// performing a loop collapse operation. -class ForSubExprChecker final : public RecursiveASTVisitor { +class ForSubExprChecker : public DynamicRecursiveASTVisitor { const llvm::SmallPtrSetImpl &CollapsedLoopVarDecls; VarDecl *ForbiddenVar = nullptr; SourceRange ErrLoc; @@ -7728,13 +7725,13 @@ class ForSubExprChecker final : public RecursiveASTVisitor { public: explicit ForSubExprChecker( const llvm::SmallPtrSetImpl &CollapsedLoopVarDecls) - : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {} - - // We want to visit implicit code, i.e. synthetic initialisation statements - // created during range-for lowering. - bool shouldVisitImplicitCode() const { return true; } + : CollapsedLoopVarDecls(CollapsedLoopVarDecls) { + // We want to visit implicit code, i.e. synthetic initialisation statements + // created during range-for lowering. + ShouldVisitImplicitCode = true; + } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { ValueDecl *VD = E->getDecl(); if (!isa(VD)) return true; @@ -9617,7 +9614,7 @@ static Expr *buildPostUpdate(Sema &S, ArrayRef PostUpdates) { /// Look for variables declared in the body parts of a for-loop nest. Used /// for verifying loop nest structure before performing a loop collapse /// operation. -class ForVarDeclFinder final : public RecursiveASTVisitor { +class ForVarDeclFinder : public DynamicRecursiveASTVisitor { int NestingDepth = 0; llvm::SmallPtrSetImpl &VarDecls; @@ -9625,21 +9622,21 @@ public: explicit ForVarDeclFinder(llvm::SmallPtrSetImpl &VD) : VarDecls(VD) {} - bool VisitForStmt(ForStmt *F) { + bool VisitForStmt(ForStmt *F) override { ++NestingDepth; TraverseStmt(F->getBody()); --NestingDepth; return false; } - bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) { + bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override { ++NestingDepth; TraverseStmt(RF->getBody()); --NestingDepth; return false; } - bool VisitVarDecl(VarDecl *D) { + bool VisitVarDecl(VarDecl *D) override { Decl *C = D->getCanonicalDecl(); if (NestingDepth > 0) VarDecls.insert(C); @@ -18690,7 +18687,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) && - !Ty.isMoreQualifiedThan(D->getType())) + !Ty.isMoreQualifiedThan(D->getType(), + SemaRef.getASTContext())) return D; return nullptr; })) { @@ -21597,7 +21595,8 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && SemaRef.IsDerivedFrom(Loc, Type, D->getType()) && - !Type.isMoreQualifiedThan(D->getType())) + !Type.isMoreQualifiedThan(D->getType(), + SemaRef.getASTContext())) return D; return nullptr; })) { @@ -21768,7 +21767,7 @@ static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * { if (!D->isInvalidDecl() && SemaRef.IsDerivedFrom(Loc, Type, D->getType()) && - !Type.isMoreQualifiedThan(D->getType())) + !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext())) return D; return nullptr; }); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 4aeceba128b29b7d5ef24c832dc029856986a925..e4bf9aa521224b997f4185c4375f2b7ae27e0468 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12,17 +12,14 @@ #include "CheckExprLifetime.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/DependenceFlags.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/OperatorKinds.h" @@ -34,7 +31,6 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/SemaCUDA.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" @@ -43,9 +39,7 @@ #include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Casting.h" #include #include #include @@ -2963,7 +2957,7 @@ static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ if (TQs == Qs) return T; - if (Qs.compatiblyIncludes(TQs)) + if (Qs.compatiblyIncludes(TQs, Context)) return Context.getQualifiedType(T, Qs); return Context.getQualifiedType(T.getUnqualifiedType(), Qs); @@ -2997,7 +2991,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType(); if (getLangOpts().CPlusPlus && LHS && RHS && !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs( - FromObjCPtr->getPointeeType())) + FromObjCPtr->getPointeeType(), getASTContext())) return false; ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, ToObjCPtr->getPointeeType(), @@ -3604,7 +3598,8 @@ static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals, static bool isQualificationConversionStep(QualType FromType, QualType ToType, bool CStyle, bool IsTopLevel, bool &PreviousToQualsIncludeConst, - bool &ObjCLifetimeConversion) { + bool &ObjCLifetimeConversion, + const ASTContext &Ctx) { Qualifiers FromQuals = FromType.getQualifiers(); Qualifiers ToQuals = ToType.getQualifiers(); @@ -3635,7 +3630,7 @@ static bool isQualificationConversionStep(QualType FromType, QualType ToType, // -- for every j > 0, if const is in cv 1,j then const is in cv // 2,j, and similarly for volatile. - if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals)) + if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals, Ctx)) return false; // If address spaces mismatch: @@ -3645,8 +3640,8 @@ static bool isQualificationConversionStep(QualType FromType, QualType ToType, // - in non-top levels it is not a valid conversion. if (ToQuals.getAddressSpace() != FromQuals.getAddressSpace() && (!IsTopLevel || - !(ToQuals.isAddressSpaceSupersetOf(FromQuals) || - (CStyle && FromQuals.isAddressSpaceSupersetOf(ToQuals))))) + !(ToQuals.isAddressSpaceSupersetOf(FromQuals, Ctx) || + (CStyle && FromQuals.isAddressSpaceSupersetOf(ToQuals, Ctx))))) return false; // -- if the cv 1,j and cv 2,j are different, then const is in @@ -3693,9 +3688,10 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, bool PreviousToQualsIncludeConst = true; bool UnwrappedAnyPointer = false; while (Context.UnwrapSimilarTypes(FromType, ToType)) { - if (!isQualificationConversionStep( - FromType, ToType, CStyle, !UnwrappedAnyPointer, - PreviousToQualsIncludeConst, ObjCLifetimeConversion)) + if (!isQualificationConversionStep(FromType, ToType, CStyle, + !UnwrappedAnyPointer, + PreviousToQualsIncludeConst, + ObjCLifetimeConversion, getASTContext())) return false; UnwrappedAnyPointer = true; } @@ -4546,9 +4542,9 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc, T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); if (isa(T2) && T2Quals) T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); - if (T2.isMoreQualifiedThan(T1)) + if (T2.isMoreQualifiedThan(T1, S.getASTContext())) return ImplicitConversionSequence::Better; - if (T1.isMoreQualifiedThan(T2)) + if (T1.isMoreQualifiedThan(T2, S.getASTContext())) return ImplicitConversionSequence::Worse; } } @@ -4987,7 +4983,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, bool ObjCLifetimeConversion = false; if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false, TopLevel, PreviousToQualsIncludeConst, - ObjCLifetimeConversion)) + ObjCLifetimeConversion, getASTContext())) return (ConvertedReferent || Context.hasSimilarType(T1, T2)) ? Ref_Related : Ref_Incompatible; @@ -5318,7 +5314,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // MS compiler ignores __unaligned qualifier for references; do the same. T1Quals.removeUnaligned(); T2Quals.removeUnaligned(); - if (!T1Quals.compatiblyIncludes(T2Quals)) + if (!T1Quals.compatiblyIncludes(T2Quals, S.getASTContext())) return ICS; } @@ -5836,7 +5832,7 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getLocalCVRQualifiers() && !ImplicitParamType.isAtLeastAsQualifiedAs( - withoutUnaligned(S.Context, FromTypeCanon))) { + withoutUnaligned(S.Context, FromTypeCanon), S.getASTContext())) { ICS.setBad(BadConversionSequence::bad_qualifiers, FromType, ImplicitParamType); return ICS; @@ -5845,7 +5841,8 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( if (FromTypeCanon.hasAddressSpace()) { Qualifiers QualsImplicitParamType = ImplicitParamType.getQualifiers(); Qualifiers QualsFromType = FromTypeCanon.getQualifiers(); - if (!QualsImplicitParamType.isAddressSpaceSupersetOf(QualsFromType)) { + if (!QualsImplicitParamType.isAddressSpaceSupersetOf(QualsFromType, + S.getASTContext())) { ICS.setBad(BadConversionSequence::bad_qualifiers, FromType, ImplicitParamType); return ICS; @@ -7030,7 +7027,7 @@ void Sema::AddOverloadCandidate( // destination address space. if (!Qualifiers::isAddressSpaceSupersetOf( Constructor->getMethodQualifiers().getAddressSpace(), - CandidateSet.getDestAS())) { + CandidateSet.getDestAS(), getASTContext())) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_object_addrspace_mismatch; } @@ -10678,9 +10675,9 @@ bool clang::isBetterOverloadCandidate( LangAS AS1 = CD1->getMethodQualifiers().getAddressSpace(); LangAS AS2 = CD2->getMethodQualifiers().getAddressSpace(); if (AS1 != AS2) { - if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1)) + if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1, S.getASTContext())) return true; - if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2)) + if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2, S.getASTContext())) return false; } } @@ -11285,7 +11282,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, } if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() && - !CToTy.isAtLeastAsQualifiedAs(CFromTy)) { + !CToTy.isAtLeastAsQualifiedAs(CFromTy, S.getASTContext())) { Qualifiers FromQs = CFromTy.getQualifiers(); Qualifiers ToQs = CToTy.getQualifiers(); @@ -11384,7 +11381,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (const PointerType *FromPtrTy = FromTy->getAs()) { if (const PointerType *ToPtrTy = ToTy->getAs()) { if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( - FromPtrTy->getPointeeType()) && + FromPtrTy->getPointeeType(), S.getASTContext()) && !FromPtrTy->getPointeeType()->isIncompleteType() && !ToPtrTy->getPointeeType()->isIncompleteType() && S.IsDerivedFrom(SourceLocation(), ToPtrTy->getPointeeType(), @@ -11398,11 +11395,12 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl()) if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl()) if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( - FromPtrTy->getPointeeType()) && + FromPtrTy->getPointeeType(), S.getASTContext()) && FromIface->isSuperClassOf(ToIface)) BaseToDerivedConversion = 2; } else if (const ReferenceType *ToRefTy = ToTy->getAs()) { - if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && + if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy, + S.getASTContext()) && !FromTy->isIncompleteType() && !ToRefTy->getPointeeType()->isIncompleteType() && S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) { @@ -14811,7 +14809,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Check for a self move. DiagnoseSelfMove(Args[0], Args[1], OpLoc); // lifetime check. - checkExprLifetime( + checkAssignmentLifetime( *this, AssignedEntity{Args[0], dyn_cast(FnDecl)}, Args[1]); } diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index c9379d25f7805c4912241a77739bf14741f11785..1db09b5105df19572c75c4eb3f0e3afeb60802ca 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -36,9 +36,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" -#include "llvm/ADT/SmallString.h" using namespace clang; using namespace sema; diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index e7cecebae258087bd43e5bb13d9f7b5a608f02ad..d4fddeb01d0fc85f5ef45d2c1ec8024a4721c529 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -14,7 +14,6 @@ #include "clang/Sema/Attr.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/Sema.h" -#include "clang/Sema/SemaDiagnostic.h" using namespace clang; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 38ae6d8116c3bb04c4a6cd0e3ee965c3d5667b1d..d6bc66246c758f228935fc588990640213a20277 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -12,16 +12,15 @@ #include "CheckExprLifetime.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/IgnoreExpr.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" @@ -35,15 +34,12 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLForwardCompat.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -204,23 +200,30 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { return true; } -static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A, - SourceLocation Loc, SourceRange R1, - SourceRange R2, bool IsCtor) { +static bool DiagnoseNoDiscard(Sema &S, const NamedDecl *OffendingDecl, + const WarnUnusedResultAttr *A, SourceLocation Loc, + SourceRange R1, SourceRange R2, bool IsCtor) { if (!A) return false; StringRef Msg = A->getMessage(); if (Msg.empty()) { + if (OffendingDecl) + return S.Diag(Loc, diag::warn_unused_return_type) + << IsCtor << A << OffendingDecl << false << R1 << R2; if (IsCtor) - return S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2; - return S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2; + return S.Diag(Loc, diag::warn_unused_constructor) + << A << false << R1 << R2; + return S.Diag(Loc, diag::warn_unused_result) << A << false << R1 << R2; } + if (OffendingDecl) + return S.Diag(Loc, diag::warn_unused_return_type) + << IsCtor << A << OffendingDecl << true << Msg << R1 << R2; if (IsCtor) - return S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1 - << R2; - return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2; + return S.Diag(Loc, diag::warn_unused_constructor) + << A << true << Msg << R1 << R2; + return S.Diag(Loc, diag::warn_unused_result) << A << true << Msg << R1 << R2; } void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { @@ -290,9 +293,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { if (E->getType()->isVoidType()) return; - if (DiagnoseNoDiscard(*this, cast_or_null( - CE->getUnusedResultAttr(Context)), - Loc, R1, R2, /*isCtor=*/false)) + auto [OffendingDecl, A] = CE->getUnusedResultAttr(Context); + if (DiagnoseNoDiscard(*this, OffendingDecl, + cast_or_null(A), Loc, R1, R2, + /*isCtor=*/false)) return; // If the callee has attribute pure, const, or warn_unused_result, warn with @@ -313,16 +317,21 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { } } else if (const auto *CE = dyn_cast(E)) { if (const CXXConstructorDecl *Ctor = CE->getConstructor()) { + const NamedDecl *OffendingDecl = nullptr; const auto *A = Ctor->getAttr(); - A = A ? A : Ctor->getParent()->getAttr(); - if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true)) + if (!A) { + OffendingDecl = Ctor->getParent(); + A = OffendingDecl->getAttr(); + } + if (DiagnoseNoDiscard(*this, OffendingDecl, A, Loc, R1, R2, + /*isCtor=*/true)) return; } } else if (const auto *ILE = dyn_cast(E)) { if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) { - if (DiagnoseNoDiscard(*this, TD->getAttr(), Loc, R1, - R2, /*isCtor=*/false)) + if (DiagnoseNoDiscard(*this, TD, TD->getAttr(), Loc, + R1, R2, /*isCtor=*/false)) return; } } else if (ShouldSuppress) @@ -336,8 +345,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { } const ObjCMethodDecl *MD = ME->getMethodDecl(); if (MD) { - if (DiagnoseNoDiscard(*this, MD->getAttr(), Loc, R1, - R2, /*isCtor=*/false)) + if (DiagnoseNoDiscard(*this, nullptr, MD->getAttr(), + Loc, R1, R2, /*isCtor=*/false)) return; } } else if (const PseudoObjectExpr *POE = dyn_cast(E)) { @@ -3606,15 +3615,15 @@ namespace { /// others. Pretend that all local typedefs are always referenced, to not warn /// on this. This isn't necessary if f has internal linkage, or the typedef /// is private. -class LocalTypedefNameReferencer - : public RecursiveASTVisitor { +class LocalTypedefNameReferencer : public DynamicRecursiveASTVisitor { public: LocalTypedefNameReferencer(Sema &S) : S(S) {} - bool VisitRecordType(const RecordType *RT); + bool VisitRecordType(RecordType *RT) override; + private: Sema &S; }; -bool LocalTypedefNameReferencer::VisitRecordType(const RecordType *RT) { +bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) { auto *R = dyn_cast(RT->getDecl()); if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() || R->isDependentType()) diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 245969a03777e979a98c0b01f1b2bc1b8759ca4e..0b272b806391c44a5d8c9021ab5411f2b331c478 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ExprCXX.h" -#include "clang/AST/GlobalDecl.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/TargetInfo.h" @@ -20,7 +19,6 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index f801455596fe6f408feb7e33932545cdf61c4a0d..106e2430de901ec022b0e04976c2ae111b412cf5 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -12,14 +12,10 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/EvaluatedExprVisitor.h" -#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DelayedDiagnostic.h" -#include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/SemaInternal.h" -#include "llvm/ADT/StringExtras.h" #include using namespace clang; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 852721944e2fa0e582467c526e10b2e7be120cc2..f6ca06fefb4912a16af0dbe04b388ef5b879f6e0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -14,9 +14,9 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateName.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/Builtins.h" @@ -24,7 +24,6 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" @@ -37,12 +36,9 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallBitVector.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include #include using namespace clang; using namespace sema; @@ -2563,9 +2559,7 @@ namespace { /// A class which looks for a use of a certain level of template /// parameter. -struct DependencyChecker : RecursiveASTVisitor { - typedef RecursiveASTVisitor super; - +struct DependencyChecker : DynamicRecursiveASTVisitor { unsigned Depth; // Whether we're looking for a use of a template parameter that makes the @@ -2603,7 +2597,7 @@ struct DependencyChecker : RecursiveASTVisitor { return false; } - bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) { + bool TraverseStmt(Stmt *S) override { // Prune out non-type-dependent expressions if requested. This can // sometimes result in us failing to find a template parameter reference // (if a value-dependent expression creates a dependent type), but this @@ -2611,51 +2605,51 @@ struct DependencyChecker : RecursiveASTVisitor { if (auto *E = dyn_cast_or_null(S)) if (IgnoreNonTypeDependent && !E->isTypeDependent()) return true; - return super::TraverseStmt(S, Q); + return DynamicRecursiveASTVisitor::TraverseStmt(S); } - bool TraverseTypeLoc(TypeLoc TL) { + bool TraverseTypeLoc(TypeLoc TL) override { if (IgnoreNonTypeDependent && !TL.isNull() && !TL.getType()->isDependentType()) return true; - return super::TraverseTypeLoc(TL); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL); } - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc()); } - bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override { // For a best-effort search, keep looking until we find a location. return IgnoreNonTypeDependent || !Matches(T->getDepth()); } - bool TraverseTemplateName(TemplateName N) { + bool TraverseTemplateName(TemplateName N) override { if (TemplateTemplateParmDecl *PD = dyn_cast_or_null(N.getAsTemplateDecl())) if (Matches(PD->getDepth())) return false; - return super::TraverseTemplateName(N); + return DynamicRecursiveASTVisitor::TraverseTemplateName(N); } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (NonTypeTemplateParmDecl *PD = dyn_cast(E->getDecl())) if (Matches(PD->getDepth(), E->getExprLoc())) return false; - return super::VisitDeclRefExpr(E); + return DynamicRecursiveASTVisitor::VisitDeclRefExpr(E); } - bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { + bool VisitSubstTemplateTypeParmType(SubstTemplateTypeParmType *T) override { return TraverseType(T->getReplacementType()); } - bool - VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { + bool VisitSubstTemplateTypeParmPackType( + SubstTemplateTypeParmPackType *T) override { return TraverseTemplateArgument(T->getArgumentPack()); } - bool TraverseInjectedClassNameType(const InjectedClassNameType *T) { + bool TraverseInjectedClassNameType(InjectedClassNameType *T) override { return TraverseType(T->getInjectedSpecializationType()); } }; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 2946d8102f9897175d9f04b5d47c9c2f7af2a6e8..62a0c30d995020e9dce5f728c6f6369a32297e48 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -20,10 +20,10 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -1743,7 +1743,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( // C++ [temp.deduct.conv]p4: // If the original A is a reference type, A can be more cv-qualified // than the deduced A - if (!A.getQualifiers().compatiblyIncludes(P.getQualifiers())) + if (!A.getQualifiers().compatiblyIncludes(P.getQualifiers(), + S.getASTContext())) return TemplateDeductionResult::NonDeducedMismatch; // Strip out all extra qualifiers from the argument to figure out the @@ -3772,7 +3773,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info, if (AQuals == DeducedAQuals) { // Qualifiers match; there's nothing to do. - } else if (!DeducedAQuals.compatiblyIncludes(AQuals)) { + } else if (!DeducedAQuals.compatiblyIncludes(AQuals, S.getASTContext())) { return Failed(); } else { // Qualifiers are compatible, so have the argument type adopt the @@ -6478,8 +6479,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( } namespace { -struct MarkUsedTemplateParameterVisitor : - RecursiveASTVisitor { +struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor { llvm::SmallBitVector &Used; unsigned Depth; @@ -6487,23 +6487,22 @@ struct MarkUsedTemplateParameterVisitor : unsigned Depth) : Used(Used), Depth(Depth) { } - bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override { if (T->getDepth() == Depth) Used[T->getIndex()] = true; return true; } - bool TraverseTemplateName(TemplateName Template) { + bool TraverseTemplateName(TemplateName Template) override { if (auto *TTP = llvm::dyn_cast_or_null( Template.getAsTemplateDecl())) if (TTP->getDepth() == Depth) Used[TTP->getIndex()] = true; - RecursiveASTVisitor:: - TraverseTemplateName(Template); + DynamicRecursiveASTVisitor::TraverseTemplateName(Template); return true; } - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (auto *NTTP = dyn_cast(E->getDecl())) if (NTTP->getDepth() == Depth) Used[NTTP->getIndex()] = true; diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index e422ef04e20d909cf0a520829885e042987081ef..d42c3765aa534fe4d7d3f69467f2e03084bd398f 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -21,10 +21,10 @@ #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/OperationKinds.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -43,7 +43,6 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" @@ -637,8 +636,7 @@ private: SmallVector TemplateParamsReferencedInTemplateArgumentList( const TemplateParameterList *TemplateParamsList, ArrayRef DeducedArgs) { - struct TemplateParamsReferencedFinder - : public RecursiveASTVisitor { + struct TemplateParamsReferencedFinder : DynamicRecursiveASTVisitor { const TemplateParameterList *TemplateParamList; llvm::BitVector ReferencedTemplateParams; @@ -647,22 +645,22 @@ SmallVector TemplateParamsReferencedInTemplateArgumentList( : TemplateParamList(TemplateParamList), ReferencedTemplateParams(TemplateParamList->size()) {} - bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) override { // We use the index and depth to retrieve the corresponding template // parameter from the parameter list, which is more robost. Mark(TTP->getDepth(), TTP->getIndex()); return true; } - bool VisitDeclRefExpr(DeclRefExpr *DRE) { + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { MarkAppeared(DRE->getFoundDecl()); return true; } - bool TraverseTemplateName(TemplateName Template) { + bool TraverseTemplateName(TemplateName Template) override { if (auto *TD = Template.getAsTemplateDecl()) MarkAppeared(TD); - return RecursiveASTVisitor::TraverseTemplateName(Template); + return DynamicRecursiveASTVisitor::TraverseTemplateName(Template); } void MarkAppeared(NamedDecl *ND) { diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3a3b5984fe740d7d8188d0c992fff68972a2cf15..4d3d1c5a85bb6367fa3389b9aed593002695adcb 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -17,20 +17,18 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/PrettyDeclStackTrace.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" -#include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaConcept.h" #include "clang/Sema/SemaInternal.h" @@ -153,9 +151,9 @@ getEnclosingTypeAliasTemplateDecl(Sema &SemaRef) { bool isLambdaEnclosedByTypeAliasDecl( const FunctionDecl *LambdaCallOperator, const TypeAliasTemplateDecl *PrimaryTypeAliasDecl) { - struct Visitor : RecursiveASTVisitor { + struct Visitor : DynamicRecursiveASTVisitor { Visitor(const FunctionDecl *CallOperator) : CallOperator(CallOperator) {} - bool VisitLambdaExpr(const LambdaExpr *LE) { + bool VisitLambdaExpr(LambdaExpr *LE) override { // Return true to bail out of the traversal, implying the Decl contains // the lambda. return getPrimaryTemplateOfGenericLambda(LE->getCallOperator()) != diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5a001843e2ba46f8fa30ec7cdb55f50e0d5dd76e..10efde7c3fe54058bf874f8971530623b360e0a3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -14,13 +14,11 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclVisitor.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/TypeLoc.h" -#include "clang/AST/TypeOrdering.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" @@ -30,7 +28,6 @@ #include "clang/Sema/SemaAMDGPU.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/SemaSwift.h" @@ -990,6 +987,7 @@ Decl * TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier()); + SemaRef.InstantiateAttrs(TemplateArgs, D, Inst, LateAttrs, StartingScope); Owner->addDecl(Inst); return Inst; } diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 153b2a1142c578d63e6971d067147961eb3afcaf..c32f794c701cd221ae6e493baf33122eea8c79ca 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -8,14 +8,15 @@ // This file implements semantic analysis for C++0x variadic templates. //===----------------------------------------------------------------------===/ -#include "clang/Sema/Sema.h" #include "TypeLocBuilder.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/Support/SaveAndRestore.h" @@ -29,16 +30,12 @@ using namespace clang; namespace { /// A class that collects unexpanded parameter packs. - class CollectUnexpandedParameterPacksVisitor : - public RecursiveASTVisitor - { - typedef RecursiveASTVisitor - inherited; +class CollectUnexpandedParameterPacksVisitor + : public DynamicRecursiveASTVisitor { + SmallVectorImpl &Unexpanded; - SmallVectorImpl &Unexpanded; - - bool InLambdaOrBlock = false; - unsigned DepthLimit = (unsigned)-1; + bool InLambdaOrBlock = false; + unsigned DepthLimit = (unsigned)-1; #ifndef NDEBUG bool ContainsIntermediatePacks = false; @@ -67,19 +64,19 @@ namespace { public: explicit CollectUnexpandedParameterPacksVisitor( SmallVectorImpl &Unexpanded) - : Unexpanded(Unexpanded) {} - - bool shouldWalkTypesOfTypeLocs() const { return false; } + : Unexpanded(Unexpanded) { + ShouldWalkTypesOfTypeLocs = false; - // We need this so we can find e.g. attributes on lambdas. - bool shouldVisitImplicitCode() const { return true; } + // We need this so we can find e.g. attributes on lambdas. + ShouldVisitImplicitCode = true; + } //------------------------------------------------------------------------ // Recording occurrences of (unexpanded) parameter packs. //------------------------------------------------------------------------ /// Record occurrences of template type parameter packs. - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { if (TL.getTypePtr()->isParameterPack()) addUnexpanded(TL.getTypePtr(), TL.getNameLoc()); return true; @@ -90,7 +87,7 @@ namespace { /// them. /// /// Ideally, this routine would never be used. - bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override { if (T->isParameterPack()) addUnexpanded(T); @@ -99,7 +96,7 @@ namespace { /// Record occurrences of function and non-type template /// parameter packs in an expression. - bool VisitDeclRefExpr(DeclRefExpr *E) { + bool VisitDeclRefExpr(DeclRefExpr *E) override { if (E->getDecl()->isParameterPack()) addUnexpanded(E->getDecl(), E->getLocation()); @@ -107,7 +104,7 @@ namespace { } /// Record occurrences of template template parameter packs. - bool TraverseTemplateName(TemplateName Template) { + bool TraverseTemplateName(TemplateName Template) override { if (auto *TTP = dyn_cast_or_null( Template.getAsTemplateDecl())) { if (TTP->isParameterPack()) @@ -119,12 +116,12 @@ namespace { (bool)Template.getAsSubstTemplateTemplateParmPack(); #endif - return inherited::TraverseTemplateName(Template); + return DynamicRecursiveASTVisitor::TraverseTemplateName(Template); } /// Suppress traversal into Objective-C container literal /// elements that are pack expansions. - bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { + bool TraverseObjCDictionaryLiteral(ObjCDictionaryLiteral *E) override { if (!E->containsUnexpandedParameterPack()) return true; @@ -144,118 +141,127 @@ namespace { /// Suppress traversal into statements and expressions that /// do not contain unexpanded parameter packs. - bool TraverseStmt(Stmt *S) { + bool TraverseStmt(Stmt *S) override { Expr *E = dyn_cast_or_null(S); if ((E && E->containsUnexpandedParameterPack()) || InLambdaOrBlock) - return inherited::TraverseStmt(S); + return DynamicRecursiveASTVisitor::TraverseStmt(S); return true; } /// Suppress traversal into types that do not contain /// unexpanded parameter packs. - bool TraverseType(QualType T) { + bool TraverseType(QualType T) override { if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambdaOrBlock) - return inherited::TraverseType(T); + return DynamicRecursiveASTVisitor::TraverseType(T); return true; } /// Suppress traversal into types with location information /// that do not contain unexpanded parameter packs. - bool TraverseTypeLoc(TypeLoc TL) { + bool TraverseTypeLoc(TypeLoc TL) override { if ((!TL.getType().isNull() && TL.getType()->containsUnexpandedParameterPack()) || InLambdaOrBlock) - return inherited::TraverseTypeLoc(TL); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL); return true; } /// Suppress traversal of parameter packs. - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { // A function parameter pack is a pack expansion, so cannot contain // an unexpanded parameter pack. Likewise for a template parameter // pack that contains any references to other packs. if (D && D->isParameterPack()) return true; - return inherited::TraverseDecl(D); + return DynamicRecursiveASTVisitor::TraverseDecl(D); } /// Suppress traversal of pack-expanded attributes. - bool TraverseAttr(Attr *A) { + bool TraverseAttr(Attr *A) override { if (A->isPackExpansion()) return true; - return inherited::TraverseAttr(A); + return DynamicRecursiveASTVisitor::TraverseAttr(A); } /// Suppress traversal of pack expansion expressions and types. ///@{ - bool TraversePackExpansionType(PackExpansionType *T) { return true; } - bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) { return true; } - bool TraversePackExpansionExpr(PackExpansionExpr *E) { return true; } - bool TraverseCXXFoldExpr(CXXFoldExpr *E) { return true; } - bool TraversePackIndexingExpr(PackIndexingExpr *E) { - return inherited::TraverseStmt(E->getIndexExpr()); + bool TraversePackExpansionType(PackExpansionType *T) override { + return true; } - bool TraversePackIndexingType(PackIndexingType *E) { - return inherited::TraverseStmt(E->getIndexExpr()); + bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) override { + return true; } - bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) { - return inherited::TraverseStmt(TL.getIndexExpr()); + bool TraversePackExpansionExpr(PackExpansionExpr *E) override { + return true; + } + bool TraverseCXXFoldExpr(CXXFoldExpr *E) override { return true; } + bool TraversePackIndexingExpr(PackIndexingExpr *E) override { + return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr()); + } + bool TraversePackIndexingType(PackIndexingType *E) override { + return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr()); + } + bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) override { + return DynamicRecursiveASTVisitor::TraverseStmt(TL.getIndexExpr()); } ///@} /// Suppress traversal of using-declaration pack expansion. - bool TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { + bool + TraverseUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) override { if (D->isPackExpansion()) return true; - return inherited::TraverseUnresolvedUsingValueDecl(D); + return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingValueDecl(D); } /// Suppress traversal of using-declaration pack expansion. - bool TraverseUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { + bool TraverseUnresolvedUsingTypenameDecl( + UnresolvedUsingTypenameDecl *D) override { if (D->isPackExpansion()) return true; - return inherited::TraverseUnresolvedUsingTypenameDecl(D); + return DynamicRecursiveASTVisitor::TraverseUnresolvedUsingTypenameDecl(D); } /// Suppress traversal of template argument pack expansions. - bool TraverseTemplateArgument(const TemplateArgument &Arg) { + bool TraverseTemplateArgument(const TemplateArgument &Arg) override { if (Arg.isPackExpansion()) return true; - return inherited::TraverseTemplateArgument(Arg); + return DynamicRecursiveASTVisitor::TraverseTemplateArgument(Arg); } /// Suppress traversal of template argument pack expansions. - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { + bool + TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override { if (ArgLoc.getArgument().isPackExpansion()) return true; - return inherited::TraverseTemplateArgumentLoc(ArgLoc); + return DynamicRecursiveASTVisitor::TraverseTemplateArgumentLoc(ArgLoc); } /// Suppress traversal of base specifier pack expansions. - bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) { + bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base) override { if (Base.isPackExpansion()) return true; - return inherited::TraverseCXXBaseSpecifier(Base); + return DynamicRecursiveASTVisitor::TraverseCXXBaseSpecifier(Base); } /// Suppress traversal of mem-initializer pack expansions. - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { if (Init->isPackExpansion()) return true; - return inherited::TraverseConstructorInitializer(Init); + return DynamicRecursiveASTVisitor::TraverseConstructorInitializer(Init); } /// Note whether we're traversing a lambda containing an unexpanded @@ -263,7 +269,7 @@ namespace { /// including all the places where we normally wouldn't look. Within a /// lambda, we don't propagate the 'contains unexpanded parameter pack' bit /// outside an expression. - bool TraverseLambdaExpr(LambdaExpr *Lambda) { + bool TraverseLambdaExpr(LambdaExpr *Lambda) override { // The ContainsUnexpandedParameterPack bit on a lambda is always correct, // even if it's contained within another lambda. if (!Lambda->containsUnexpandedParameterPack()) @@ -275,57 +281,58 @@ namespace { if (auto *TPL = Lambda->getTemplateParameterList()) DepthLimit = TPL->getDepth(); - inherited::TraverseLambdaExpr(Lambda); + DynamicRecursiveASTVisitor::TraverseLambdaExpr(Lambda); DepthLimit = OldDepthLimit; return true; } /// Analogously for blocks. - bool TraverseBlockExpr(BlockExpr *Block) { + bool TraverseBlockExpr(BlockExpr *Block) override { if (!Block->containsUnexpandedParameterPack()) return true; SaveAndRestore _(InLambdaOrBlock, true); - inherited::TraverseBlockExpr(Block); + DynamicRecursiveASTVisitor::TraverseBlockExpr(Block); return true; } /// Suppress traversal within pack expansions in lambda captures. bool TraverseLambdaCapture(LambdaExpr *Lambda, const LambdaCapture *C, - Expr *Init) { + Expr *Init) override { if (C->isPackExpansion()) return true; - return inherited::TraverseLambdaCapture(Lambda, C, Init); + return DynamicRecursiveASTVisitor::TraverseLambdaCapture(Lambda, C, Init); } #ifndef NDEBUG - bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) { + bool TraverseFunctionParmPackExpr(FunctionParmPackExpr *) override { ContainsIntermediatePacks = true; return true; } bool TraverseSubstNonTypeTemplateParmPackExpr( - SubstNonTypeTemplateParmPackExpr *) { + SubstNonTypeTemplateParmPackExpr *) override { ContainsIntermediatePacks = true; return true; } - bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *) { + bool VisitSubstTemplateTypeParmPackType( + SubstTemplateTypeParmPackType *) override { ContainsIntermediatePacks = true; return true; } - bool - VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc) { + bool VisitSubstTemplateTypeParmPackTypeLoc( + SubstTemplateTypeParmPackTypeLoc) override { ContainsIntermediatePacks = true; return true; } bool containsIntermediatePacks() const { return ContainsIntermediatePacks; } #endif - }; +}; } /// Determine whether it's possible for an unexpanded parameter pack to diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 6c738eb87a6b1b8214e2bb9e3577cbefe89e5c9a..a1f111ac2709c6f4b4f804a97fcfecc6669f2351 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -26,7 +26,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" @@ -39,18 +38,14 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" -#include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLForwardCompat.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include #include @@ -4954,9 +4949,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, cast(T)->getKeyword() != AutoTypeKeyword::Auto || cast(T)->isConstrained())) { - S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), - diag::err_trailing_return_without_auto) - << T << D.getDeclSpec().getSourceRange(); + // Attach a valid source location for diagnostics on functions with + // trailing return types missing 'auto'. Attempt to get the location + // from the declared type; if invalid, fall back to the trailing + // return type's location. + SourceLocation Loc = D.getDeclSpec().getTypeSpecTypeLoc(); + SourceRange SR = D.getDeclSpec().getSourceRange(); + if (Loc.isInvalid()) { + Loc = FTI.getTrailingReturnTypeLoc(); + SR = D.getSourceRange(); + } + S.Diag(Loc, diag::err_trailing_return_without_auto) << T << SR; D.setInvalidType(true); // FIXME: recover and fill decls in `TypeLoc`s. AreDeclaratorChunksValid = false; @@ -5904,6 +5907,30 @@ static void fillMatrixTypeLoc(MatrixTypeLoc MTL, llvm_unreachable("no matrix_type attribute found at the expected location!"); } +static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { + SourceLocation Loc; + switch (Chunk.Kind) { + case DeclaratorChunk::Function: + case DeclaratorChunk::Array: + case DeclaratorChunk::Paren: + case DeclaratorChunk::Pipe: + llvm_unreachable("cannot be _Atomic qualified"); + + case DeclaratorChunk::Pointer: + Loc = Chunk.Ptr.AtomicQualLoc; + break; + + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::MemberPointer: + // FIXME: Provide a source location for the _Atomic keyword. + break; + } + + ATL.setKWLoc(Loc); + ATL.setParensRange(SourceRange()); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor { Sema &SemaRef; @@ -6290,6 +6317,9 @@ namespace { void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { TL.setNameLoc(Chunk.Loc); } + void VisitAtomicTypeLoc(AtomicTypeLoc TL) { + fillAtomicQualLoc(TL, Chunk); + } void VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) { TL.setNameLoc(Chunk.Loc); @@ -6304,30 +6334,6 @@ namespace { }; } // end anonymous namespace -static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { - SourceLocation Loc; - switch (Chunk.Kind) { - case DeclaratorChunk::Function: - case DeclaratorChunk::Array: - case DeclaratorChunk::Paren: - case DeclaratorChunk::Pipe: - llvm_unreachable("cannot be _Atomic qualified"); - - case DeclaratorChunk::Pointer: - Loc = Chunk.Ptr.AtomicQualLoc; - break; - - case DeclaratorChunk::BlockPointer: - case DeclaratorChunk::Reference: - case DeclaratorChunk::MemberPointer: - // FIXME: Provide a source location for the _Atomic keyword. - break; - } - - ATL.setKWLoc(Loc); - ATL.setParensRange(SourceRange()); -} - static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, const ParsedAttributesView &Attrs) { @@ -8676,6 +8682,15 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State, } } +static void HandleLifetimeCaptureByAttr(TypeProcessingState &State, + QualType &CurType, ParsedAttr &PA) { + if (State.getDeclarator().isDeclarationOfFunction()) { + auto *Attr = State.getSema().ParseLifetimeCaptureByAttr(PA, "this"); + if (Attr) + CurType = State.getAttributedType(Attr, CurType, CurType); + } +} + static void HandleHLSLParamModifierAttr(TypeProcessingState &State, QualType &CurType, const ParsedAttr &Attr, Sema &S) { @@ -8837,6 +8852,10 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (TAL == TAL_DeclChunk) HandleLifetimeBoundAttr(state, type, attr); break; + case ParsedAttr::AT_LifetimeCaptureBy: + if (TAL == TAL_DeclChunk) + HandleLifetimeCaptureByAttr(state, type, attr); + break; case ParsedAttr::AT_NoDeref: { // FIXME: `noderef` currently doesn't work correctly in [[]] syntax. @@ -9113,7 +9132,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, } bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) { - llvm::DenseSet> NonEquivalentDecls; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls; if (!Suggested) return false; diff --git a/clang/lib/Sema/SemaX86.cpp b/clang/lib/Sema/SemaX86.cpp index 85b195491025d36abcdd1eff20307821ca67ffba..0b4b78c5b15dc52da6ccdeeae29c2dcb88ee7d3a 100644 --- a/clang/lib/Sema/SemaX86.cpp +++ b/clang/lib/Sema/SemaX86.cpp @@ -660,10 +660,16 @@ bool SemaX86::CheckBuiltinTileArguments(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_tdpbhf8ps: case X86::BI__builtin_ia32_tdphbf8ps: case X86::BI__builtin_ia32_tdphf8ps: + case X86::BI__builtin_ia32_ttdpbf16ps: + case X86::BI__builtin_ia32_ttdpfp16ps: + case X86::BI__builtin_ia32_ttcmmimfp16ps: + case X86::BI__builtin_ia32_ttcmmrlfp16ps: + case X86::BI__builtin_ia32_tconjtcmmimfp16ps: case X86::BI__builtin_ia32_tmmultf32ps: case X86::BI__builtin_ia32_ttmmultf32ps: return CheckBuiltinTileRangeAndDuplicate(TheCall, {0, 1, 2}); case X86::BI__builtin_ia32_ttransposed: + case X86::BI__builtin_ia32_tconjtfp16: return CheckBuiltinTileArgumentsRange(TheCall, {0, 1}); } } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8f23ed69c8b7487ada79a2c07c09ad4035b52203..1182d6240832615f503c739e9f9057a708151c52 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4161,6 +4161,16 @@ public: OpenACCDirectiveKind::Loop, BeginLoc, DirLoc, EndLoc, Clauses, Loop); } + StmtResult RebuildOpenACCCombinedConstruct(OpenACCDirectiveKind K, + SourceLocation BeginLoc, + SourceLocation DirLoc, + SourceLocation EndLoc, + ArrayRef Clauses, + StmtResult Loop) { + return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, DirLoc, + EndLoc, Clauses, Loop); + } + ExprResult RebuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) { return getSema().OpenACC().ActOnOpenACCAsteriskSizeExpr(AsteriskLoc); } @@ -12330,6 +12340,32 @@ TreeTransform::TransformOpenACCLoopConstruct(OpenACCLoopConstruct *C) { TransformedClauses, Loop); } +template +StmtResult TreeTransform::TransformOpenACCCombinedConstruct( + OpenACCCombinedConstruct *C) { + getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc()); + + llvm::SmallVector TransformedClauses = + getDerived().TransformOpenACCClauseList(C->getDirectiveKind(), + C->clauses()); + + if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(), + C->getBeginLoc())) + return StmtError(); + + // Transform Loop. + SemaOpenACC::AssociatedStmtRAII AssocStmtRAII( + getSema().OpenACC(), C->getDirectiveKind(), C->getDirectiveLoc(), + C->clauses(), TransformedClauses); + StmtResult Loop = getDerived().TransformStmt(C->getLoop()); + Loop = getSema().OpenACC().ActOnAssociatedStmt( + C->getBeginLoc(), C->getDirectiveKind(), TransformedClauses, Loop); + + return getDerived().RebuildOpenACCCombinedConstruct( + C->getDirectiveKind(), C->getBeginLoc(), C->getDirectiveLoc(), + C->getEndLoc(), TransformedClauses, Loop); +} + template ExprResult TreeTransform::TransformOpenACCAsteriskSizeExpr( OpenACCAsteriskSizeExpr *E) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 40e4335a11887c50a1754fe0465497a384ecca61..14be9dab4a50da9efd78b28d86bacd859f97a2e9 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3092,98 +3092,97 @@ ASTReader::ReadControlBlock(ModuleFile &F, break; } - case IMPORTS: { + case IMPORT: { // Validate the AST before processing any imports (otherwise, untangling // them can be error-prone and expensive). A module will have a name and // will already have been validated, but this catches the PCH case. if (ASTReadResult Result = readUnhashedControlBlockOnce()) return Result; - // Load each of the imported PCH files. - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - // Read information about the AST file. - ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; - // Whether we're importing a standard c++ module. - bool IsImportingStdCXXModule = Record[Idx++]; - // The import location will be the local one for now; we will adjust - // all import locations of module imports after the global source - // location info are setup, in ReadAST. - auto [ImportLoc, ImportModuleFileIndex] = - ReadUntranslatedSourceLocation(Record[Idx++]); - // The import location must belong to the current module file itself. - assert(ImportModuleFileIndex == 0); - off_t StoredSize = !IsImportingStdCXXModule ? (off_t)Record[Idx++] : 0; - time_t StoredModTime = - !IsImportingStdCXXModule ? (time_t)Record[Idx++] : 0; - - ASTFileSignature StoredSignature; - if (!IsImportingStdCXXModule) { - auto FirstSignatureByte = Record.begin() + Idx; - StoredSignature = ASTFileSignature::create( - FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size); - Idx += ASTFileSignature::size; - } + unsigned Idx = 0; + // Read information about the AST file. + ModuleKind ImportedKind = (ModuleKind)Record[Idx++]; + + // The import location will be the local one for now; we will adjust + // all import locations of module imports after the global source + // location info are setup, in ReadAST. + auto [ImportLoc, ImportModuleFileIndex] = + ReadUntranslatedSourceLocation(Record[Idx++]); + // The import location must belong to the current module file itself. + assert(ImportModuleFileIndex == 0); + + StringRef ImportedName = ReadStringBlob(Record, Idx, Blob); + + bool IsImportingStdCXXModule = Record[Idx++]; + + off_t StoredSize = 0; + time_t StoredModTime = 0; + ASTFileSignature StoredSignature; + std::string ImportedFile; + + // For prebuilt and explicit modules first consult the file map for + // an override. Note that here we don't search prebuilt module + // directories if we're not importing standard c++ module, only the + // explicit name to file mappings. Also, we will still verify the + // size/signature making sure it is essentially the same file but + // perhaps in a different location. + if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule) + ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName( + ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule); + + if (IsImportingStdCXXModule && ImportedFile.empty()) { + Diag(diag::err_failed_to_find_module_file) << ImportedName; + return Missing; + } - std::string ImportedName = ReadString(Record, Idx); - std::string ImportedFile; - - // For prebuilt and explicit modules first consult the file map for - // an override. Note that here we don't search prebuilt module - // directories if we're not importing standard c++ module, only the - // explicit name to file mappings. Also, we will still verify the - // size/signature making sure it is essentially the same file but - // perhaps in a different location. - if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule) - ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName( - ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule); - - // For C++20 Modules, we won't record the path to the imported modules - // in the BMI - if (!IsImportingStdCXXModule) { - if (ImportedFile.empty()) { - // Use BaseDirectoryAsWritten to ensure we use the same path in the - // ModuleCache as when writing. - ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx); - } else - SkipPath(Record, Idx); - } else if (ImportedFile.empty()) { - Diag(clang::diag::err_failed_to_find_module_file) << ImportedName; - return Missing; - } + if (!IsImportingStdCXXModule) { + StoredSize = (off_t)Record[Idx++]; + StoredModTime = (time_t)Record[Idx++]; - // If our client can't cope with us being out of date, we can't cope with - // our dependency being missing. - unsigned Capabilities = ClientLoadCapabilities; - if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) - Capabilities &= ~ARR_Missing; - - // Load the AST file. - auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, - Loaded, StoredSize, StoredModTime, - StoredSignature, Capabilities); - - // If we diagnosed a problem, produce a backtrace. - bool recompilingFinalized = - Result == OutOfDate && (Capabilities & ARR_OutOfDate) && - getModuleManager().getModuleCache().isPCMFinal(F.FileName); - if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized) - Diag(diag::note_module_file_imported_by) - << F.FileName << !F.ModuleName.empty() << F.ModuleName; - if (recompilingFinalized) - Diag(diag::note_module_file_conflict); - - switch (Result) { - case Failure: return Failure; - // If we have to ignore the dependency, we'll have to ignore this too. - case Missing: - case OutOfDate: return OutOfDate; - case VersionMismatch: return VersionMismatch; - case ConfigurationMismatch: return ConfigurationMismatch; - case HadErrors: return HadErrors; - case Success: break; + StringRef SignatureBytes = Blob.substr(0, ASTFileSignature::size); + StoredSignature = ASTFileSignature::create(SignatureBytes.begin(), + SignatureBytes.end()); + Blob = Blob.substr(ASTFileSignature::size); + + if (ImportedFile.empty()) { + // Use BaseDirectoryAsWritten to ensure we use the same path in the + // ModuleCache as when writing. + ImportedFile = + ReadPathBlob(BaseDirectoryAsWritten, Record, Idx, Blob); } } + + // If our client can't cope with us being out of date, we can't cope with + // our dependency being missing. + unsigned Capabilities = ClientLoadCapabilities; + if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) + Capabilities &= ~ARR_Missing; + + // Load the AST file. + auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, + Loaded, StoredSize, StoredModTime, + StoredSignature, Capabilities); + + // If we diagnosed a problem, produce a backtrace. + bool recompilingFinalized = + Result == OutOfDate && (Capabilities & ARR_OutOfDate) && + getModuleManager().getModuleCache().isPCMFinal(F.FileName); + if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized) + Diag(diag::note_module_file_imported_by) + << F.FileName << !F.ModuleName.empty() << F.ModuleName; + if (recompilingFinalized) + Diag(diag::note_module_file_conflict); + + switch (Result) { + case Failure: return Failure; + // If we have to ignore the dependency, we'll have to ignore this too. + case Missing: + case OutOfDate: return OutOfDate; + case VersionMismatch: return VersionMismatch; + case ConfigurationMismatch: return ConfigurationMismatch; + case HadErrors: return HadErrors; + case Success: break; + } break; } @@ -5624,36 +5623,38 @@ bool ASTReader::readASTFileControlBlock( break; } - case IMPORTS: { + case IMPORT: { if (!NeedsImports) break; - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - // Read information about the AST file. + unsigned Idx = 0; + // Read information about the AST file. + + // Skip Kind + Idx++; - // Skip Kind - Idx++; - bool IsStandardCXXModule = Record[Idx++]; + // Skip ImportLoc + Idx++; - // Skip ImportLoc - Idx++; + StringRef ModuleName = ReadStringBlob(Record, Idx, Blob); - // In C++20 Modules, we don't record the path to imported - // modules in the BMI files. - if (IsStandardCXXModule) { - std::string ModuleName = ReadString(Record, Idx); - Listener.visitImport(ModuleName, /*Filename=*/""); - continue; - } + bool IsStandardCXXModule = Record[Idx++]; - // Skip Size, ModTime and Signature - Idx += 1 + 1 + ASTFileSignature::size; - std::string ModuleName = ReadString(Record, Idx); - std::string FilenameStr = ReadString(Record, Idx); - auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir); - Listener.visitImport(ModuleName, *Filename); + // In C++20 Modules, we don't record the path to imported + // modules in the BMI files. + if (IsStandardCXXModule) { + Listener.visitImport(ModuleName, /*Filename=*/""); + continue; } + + // Skip Size and ModTime. + Idx += 1 + 1; + // Skip signature. + Blob = Blob.substr(ASTFileSignature::size); + + StringRef FilenameStr = ReadStringBlob(Record, Idx, Blob); + auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir); + Listener.visitImport(ModuleName, *Filename); break; } @@ -9602,6 +9603,14 @@ std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) { return Result; } +StringRef ASTReader::ReadStringBlob(const RecordDataImpl &Record, unsigned &Idx, + StringRef &Blob) { + unsigned Len = Record[Idx++]; + StringRef Result = Blob.substr(0, Len); + Blob = Blob.substr(Len); + return Result; +} + std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx) { return ReadPath(F.BaseDirectory, Record, Idx); @@ -9613,6 +9622,13 @@ std::string ASTReader::ReadPath(StringRef BaseDirectory, return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory); } +std::string ASTReader::ReadPathBlob(StringRef BaseDirectory, + const RecordData &Record, unsigned &Idx, + StringRef &Blob) { + StringRef Filename = ReadStringBlob(Record, Idx, Blob); + return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory); +} + VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record, unsigned &Idx) { unsigned Major = Record[Idx++]; @@ -9909,7 +9925,7 @@ void ASTReader::finishPendingActions() { auto ExtensionsPair = PendingObjCExtensionIvarRedeclarations.back().first; auto DuplicateIvars = PendingObjCExtensionIvarRedeclarations.back().second; - llvm::DenseSet> NonEquivalentDecls; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls; StructuralEquivalenceContext Ctx( ExtensionsPair.first->getASTContext(), ExtensionsPair.second->getASTContext(), NonEquivalentDecls, diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 33fcddbbdb2f155da5a0eda8b28a1d282d48789c..6ece3ba7af9f4b6658b9306fc74f62fd2c1eecb4 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -4447,7 +4447,7 @@ namespace { ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()]; if (Existing && Reader.getOwningModuleFile(Existing) != Reader.getOwningModuleFile(Cat)) { - llvm::DenseSet> NonEquivalentDecls; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls; StructuralEquivalenceContext Ctx( Cat->getASTContext(), Existing->getASTContext(), NonEquivalentDecls, StructuralEquivalenceKind::Default, diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 6c777c1af710ee52e1b4c7d443de2a43427314bd..a99c8cf97d4ebf171cbc46a99584f6cf3d74cd92 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2883,6 +2883,11 @@ void ASTStmtReader::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) { S->ParentComputeConstructKind = Record.readEnum(); } +void ASTStmtReader::VisitOpenACCCombinedConstruct(OpenACCCombinedConstruct *S) { + VisitStmt(S); + VisitOpenACCAssociatedStmtConstruct(S); +} + //===----------------------------------------------------------------------===// // HLSL Constructs/Directives. //===----------------------------------------------------------------------===// @@ -4405,6 +4410,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = OpenACCLoopConstruct::CreateEmpty(Context, NumClauses); break; } + case STMT_OPENACC_COMBINED_CONSTRUCT: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + S = OpenACCCombinedConstruct::CreateEmpty(Context, NumClauses); + break; + } case EXPR_REQUIRES: { unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields]; unsigned numRequirement = Record[ASTStmtReader::NumExprFields + 1]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 21471089504eb34025184323019c90d493d6a73d..f314d27b1ab30ff22afe45211c0b1bc191e1c09d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -878,7 +878,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(MODULE_NAME); RECORD(MODULE_DIRECTORY); RECORD(MODULE_MAP_FILE); - RECORD(IMPORTS); + RECORD(IMPORT); RECORD(ORIGINAL_FILE); RECORD(ORIGINAL_FILE_ID); RECORD(INPUT_FILE_OFFSETS); @@ -1536,34 +1536,53 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) { // Imports if (Chain) { - serialization::ModuleManager &Mgr = Chain->getModuleManager(); - Record.clear(); + auto Abbrev = std::make_shared(); + Abbrev->Add(BitCodeAbbrevOp(IMPORT)); + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Kind + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ImportLoc + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Module name len + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Standard C++ mod + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File size + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File timestamp + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File name len + Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Strings + unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev)); - for (ModuleFile &M : Mgr) { + SmallString<128> Blob; + + for (ModuleFile &M : Chain->getModuleManager()) { // Skip modules that weren't directly imported. if (!M.isDirectlyImported()) continue; + Record.clear(); + Blob.clear(); + + Record.push_back(IMPORT); Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding - Record.push_back(M.StandardCXXModule); AddSourceLocation(M.ImportLoc, Record); + AddStringBlob(M.ModuleName, Record, Blob); + Record.push_back(M.StandardCXXModule); // We don't want to hard code the information about imported modules // in the C++20 named modules. - if (!M.StandardCXXModule) { + if (M.StandardCXXModule) { + Record.push_back(0); + Record.push_back(0); + Record.push_back(0); + } else { // If we have calculated signature, there is no need to store // the size or timestamp. Record.push_back(M.Signature ? 0 : M.File.getSize()); Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File)); - llvm::append_range(Record, M.Signature); - } - AddString(M.ModuleName, Record); + llvm::append_range(Blob, M.Signature); - if (!M.StandardCXXModule) - AddPath(M.FileName, Record); + AddPathBlob(M.FileName, Record, Blob); + } + + Stream.EmitRecordWithBlob(AbbrevCode, Record, Blob); } - Stream.EmitRecord(IMPORTS, Record); } // Write the options block. @@ -4777,6 +4796,12 @@ void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) { Record.insert(Record.end(), Str.begin(), Str.end()); } +void ASTWriter::AddStringBlob(StringRef Str, RecordDataImpl &Record, + SmallVectorImpl &Blob) { + Record.push_back(Str.size()); + Blob.insert(Blob.end(), Str.begin(), Str.end()); +} + bool ASTWriter::PreparePathForOutput(SmallVectorImpl &Path) { assert(WritingAST && "can't prepare path for output when not writing AST"); @@ -4805,6 +4830,13 @@ void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) { AddString(FilePath, Record); } +void ASTWriter::AddPathBlob(StringRef Path, RecordDataImpl &Record, + SmallVectorImpl &Blob) { + SmallString<128> FilePath(Path); + PreparePathForOutput(FilePath); + AddStringBlob(FilePath, Record, Blob); +} + void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, StringRef Path) { SmallString<128> FilePath(Path); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 506e93b517293e7e1ff3ed3b94e8aaf021dc7e6c..ceed3ae76a3e2d59bd4cdc0cb494e5ed66749343 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2966,6 +2966,12 @@ void ASTStmtWriter::VisitOpenACCLoopConstruct(OpenACCLoopConstruct *S) { Code = serialization::STMT_OPENACC_LOOP_CONSTRUCT; } +void ASTStmtWriter::VisitOpenACCCombinedConstruct(OpenACCCombinedConstruct *S) { + VisitStmt(S); + VisitOpenACCAssociatedStmtConstruct(S); + Code = serialization::STMT_OPENACC_COMBINED_CONSTRUCT; +} + //===----------------------------------------------------------------------===// // HLSL Constructs/Directives. //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index 9c48712a0b3fbeb19aa27edf3834ee570f0a4029..4b920fccecac3dfae8078e0f366504253bbf38ce 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -614,62 +614,58 @@ llvm::Error GlobalModuleIndexBuilder::loadModuleFile(FileEntryRef File) { unsigned Code = MaybeCode.get(); // Handle module dependencies. - if (State == ControlBlock && Code == IMPORTS) { - // Load each of the imported PCH files. - unsigned Idx = 0, N = Record.size(); - while (Idx < N) { - // Read information about the AST file. - - // Skip the imported kind - ++Idx; - - // Skip if it is standard C++ module - ++Idx; - - // Skip the import location - ++Idx; - - // Load stored size/modification time. - off_t StoredSize = (off_t)Record[Idx++]; - time_t StoredModTime = (time_t)Record[Idx++]; - - // Skip the stored signature. - // FIXME: we could read the signature out of the import and validate it. - auto FirstSignatureByte = Record.begin() + Idx; - ASTFileSignature StoredSignature = ASTFileSignature::create( - FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size); - Idx += ASTFileSignature::size; - - // Skip the module name (currently this is only used for prebuilt - // modules while here we are only dealing with cached). - Idx += Record[Idx] + 1; - - // Retrieve the imported file name. - unsigned Length = Record[Idx++]; - SmallString<128> ImportedFile(Record.begin() + Idx, - Record.begin() + Idx + Length); - Idx += Length; - - // Find the imported module file. - auto DependsOnFile = - FileMgr.getOptionalFileRef(ImportedFile, /*OpenFile=*/false, - /*CacheFailure=*/false); - - if (!DependsOnFile) - return llvm::createStringError(std::errc::bad_file_descriptor, - "imported file \"%s\" not found", - ImportedFile.c_str()); - - // Save the information in ImportedModuleFileInfo so we can verify after - // loading all pcms. - ImportedModuleFiles.insert(std::make_pair( - *DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime, - StoredSignature))); - - // Record the dependency. - unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID; - getModuleFileInfo(File).Dependencies.push_back(DependsOnID); - } + if (State == ControlBlock && Code == IMPORT) { + unsigned Idx = 0; + // Read information about the AST file. + + // Skip the imported kind + ++Idx; + + // Skip the import location + ++Idx; + + // Skip the module name (currently this is only used for prebuilt + // modules while here we are only dealing with cached). + Blob = Blob.substr(Record[Idx++]); + + // Skip if it is standard C++ module + ++Idx; + + // Load stored size/modification time. + off_t StoredSize = (off_t)Record[Idx++]; + time_t StoredModTime = (time_t)Record[Idx++]; + + // Skip the stored signature. + // FIXME: we could read the signature out of the import and validate it. + StringRef SignatureBytes = Blob.substr(0, ASTFileSignature::size); + auto StoredSignature = ASTFileSignature::create(SignatureBytes.begin(), + SignatureBytes.end()); + Blob = Blob.substr(ASTFileSignature::size); + + // Retrieve the imported file name. + unsigned Length = Record[Idx++]; + StringRef ImportedFile = Blob.substr(0, Length); + Blob = Blob.substr(Length); + + // Find the imported module file. + auto DependsOnFile = + FileMgr.getOptionalFileRef(ImportedFile, /*OpenFile=*/false, + /*CacheFailure=*/false); + + if (!DependsOnFile) + return llvm::createStringError(std::errc::bad_file_descriptor, + "imported file \"%s\" not found", + std::string(ImportedFile).c_str()); + + // Save the information in ImportedModuleFileInfo so we can verify after + // loading all pcms. + ImportedModuleFiles.insert(std::make_pair( + *DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime, + StoredSignature))); + + // Record the dependency. + unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID; + getModuleFileInfo(File).Dependencies.push_back(DependsOnID); continue; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp index e674ec43bcd9df5c6ac8eefb398ea6380110029d..3e87ad09b05ee267a5d83729b75540857ba16df4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" @@ -23,7 +23,7 @@ using namespace clang; using namespace ento; namespace { -class CastToStructVisitor : public RecursiveASTVisitor { +class CastToStructVisitor : public DynamicRecursiveASTVisitor { BugReporter &BR; const CheckerBase *Checker; AnalysisDeclContext *AC; @@ -32,11 +32,11 @@ public: explicit CastToStructVisitor(BugReporter &B, const CheckerBase *Checker, AnalysisDeclContext *A) : BR(B), Checker(Checker), AC(A) {} - bool VisitCastExpr(const CastExpr *CE); + bool VisitCastExpr(CastExpr *CE) override; }; } -bool CastToStructVisitor::VisitCastExpr(const CastExpr *CE) { +bool CastToStructVisitor::VisitCastExpr(CastExpr *CE) { const Expr *E = CE->getSubExpr(); ASTContext &Ctx = AC->getASTContext(); QualType OrigTy = Ctx.getCanonicalType(E->getType()); diff --git a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp index 86f446fc411ca2bdccd1e044f60f7525790ad133..4e3919ef0166747db0bcf70c345773cbdb5853da 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp @@ -13,8 +13,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" @@ -32,27 +32,27 @@ using namespace ento; namespace { /// A simple visitor to record what VarDecls occur in EH-handling code. -class EHCodeVisitor : public RecursiveASTVisitor { +class EHCodeVisitor : public DynamicRecursiveASTVisitor { public: bool inEH; llvm::DenseSet &S; - bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { + bool TraverseObjCAtFinallyStmt(ObjCAtFinallyStmt *S) override { SaveAndRestore inFinally(inEH, true); - return ::RecursiveASTVisitor::TraverseObjCAtFinallyStmt(S); + return DynamicRecursiveASTVisitor::TraverseObjCAtFinallyStmt(S); } - bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) { + bool TraverseObjCAtCatchStmt(ObjCAtCatchStmt *S) override { SaveAndRestore inCatch(inEH, true); - return ::RecursiveASTVisitor::TraverseObjCAtCatchStmt(S); + return DynamicRecursiveASTVisitor::TraverseObjCAtCatchStmt(S); } - bool TraverseCXXCatchStmt(CXXCatchStmt *S) { + bool TraverseCXXCatchStmt(CXXCatchStmt *S) override { SaveAndRestore inCatch(inEH, true); return TraverseStmt(S->getHandlerBlock()); } - bool VisitDeclRefExpr(DeclRefExpr *DR) { + bool VisitDeclRefExpr(DeclRefExpr *DR) override { if (inEH) if (const VarDecl *D = dyn_cast(DR->getDecl())) S.insert(D); diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 034774a252b11802dfe1206ce785abdb6bcce8f5..a0bf776b11f5317dfdb3372c0a78666422a00b1b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -20,8 +20,8 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -711,10 +711,10 @@ static bool isObjCTypeParamDependent(QualType Type) { // an Objective-C type can only be dependent on a type parameter when the type // parameter structurally present in the type itself. class IsObjCTypeParamDependentTypeVisitor - : public RecursiveASTVisitor { + : public DynamicRecursiveASTVisitor { public: IsObjCTypeParamDependentTypeVisitor() = default; - bool VisitObjCTypeParamType(const ObjCTypeParamType *Type) { + bool VisitObjCTypeParamType(ObjCTypeParamType *Type) override { if (isa(Type->getDecl())) { Result = true; return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp index 7ac34ef8164e4c20eee1e1427edba4252b9bc9f5..45642483dd4578a51591ed77fd285d613dc3a178 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp @@ -15,8 +15,8 @@ /// //===----------------------------------------------------------------------===// +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" @@ -32,8 +32,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, //===----------------------------------------------------------------------===// namespace { -class FindIdenticalExprVisitor - : public RecursiveASTVisitor { +class FindIdenticalExprVisitor : public DynamicRecursiveASTVisitor { BugReporter &BR; const CheckerBase *Checker; AnalysisDeclContext *AC; @@ -45,9 +44,9 @@ public: // FindIdenticalExprVisitor only visits nodes // that are binary operators, if statements or // conditional operators. - bool VisitBinaryOperator(const BinaryOperator *B); - bool VisitIfStmt(const IfStmt *I); - bool VisitConditionalOperator(const ConditionalOperator *C); + bool VisitBinaryOperator(BinaryOperator *B) override; + bool VisitIfStmt(IfStmt *I) override; + bool VisitConditionalOperator(ConditionalOperator *C) override; private: void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise, @@ -103,7 +102,7 @@ void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B, } } -bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { +bool FindIdenticalExprVisitor::VisitIfStmt(IfStmt *I) { const Stmt *Stmt1 = I->getThen(); const Stmt *Stmt2 = I->getElse(); @@ -178,7 +177,7 @@ bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { return true; } -bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) { +bool FindIdenticalExprVisitor::VisitBinaryOperator(BinaryOperator *B) { BinaryOperator::Opcode Op = B->getOpcode(); if (BinaryOperator::isBitwiseOp(Op)) @@ -268,7 +267,7 @@ void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) { } bool FindIdenticalExprVisitor::VisitConditionalOperator( - const ConditionalOperator *C) { + ConditionalOperator *C) { // Check if expressions in conditional expression are identical // from a symbolic point of view. diff --git a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp index e1ad5911ea0b70674f9589c689b87e595dc5b6dc..ddcf0469e030e69de2e7a515be16b4dc034d2bc9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -17,7 +17,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" @@ -1189,7 +1189,7 @@ namespace { class PluralMisuseChecker : public Checker { // A helper class, which walks the AST - class MethodCrawler : public RecursiveASTVisitor { + class MethodCrawler : public DynamicRecursiveASTVisitor { BugReporter &BR; const CheckerBase *Checker; AnalysisDeclContext *AC; @@ -1207,13 +1207,13 @@ class PluralMisuseChecker : public Checker { AnalysisDeclContext *InAC) : BR(InBR), Checker(Checker), AC(InAC) {} - bool VisitIfStmt(const IfStmt *I); + bool VisitIfStmt(IfStmt *I) override; bool EndVisitIfStmt(IfStmt *I); - bool TraverseIfStmt(IfStmt *x); - bool VisitConditionalOperator(const ConditionalOperator *C); - bool TraverseConditionalOperator(ConditionalOperator *C); - bool VisitCallExpr(const CallExpr *CE); - bool VisitObjCMessageExpr(const ObjCMessageExpr *ME); + bool TraverseIfStmt(IfStmt *x) override; + bool VisitConditionalOperator(ConditionalOperator *C) override; + bool TraverseConditionalOperator(ConditionalOperator *C) override; + bool VisitCallExpr(CallExpr *CE) override; + bool VisitObjCMessageExpr(ObjCMessageExpr *ME) override; private: void reportPluralMisuseError(const Stmt *S) const; @@ -1272,7 +1272,7 @@ bool PluralMisuseChecker::MethodCrawler::isCheckingPlurality( // has been shown to almost always be a function that returns a localized // string. Raise a diagnostic when this is in a statement that matches // the condition. -bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) { +bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(CallExpr *CE) { if (InMatchingStatement) { if (const FunctionDecl *FD = CE->getDirectCallee()) { std::string NormalizedName = @@ -1294,7 +1294,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitCallExpr(const CallExpr *CE) { // diagnostic when this is in a statement that matches // the condition. bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr( - const ObjCMessageExpr *ME) { + ObjCMessageExpr *ME) { const ObjCInterfaceDecl *OD = ME->getReceiverInterface(); if (!OD) return true; @@ -1312,7 +1312,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitObjCMessageExpr( /// Override TraverseIfStmt so we know when we are done traversing an IfStmt bool PluralMisuseChecker::MethodCrawler::TraverseIfStmt(IfStmt *I) { - RecursiveASTVisitor::TraverseIfStmt(I); + DynamicRecursiveASTVisitor::TraverseIfStmt(I); return EndVisitIfStmt(I); } @@ -1331,7 +1331,7 @@ bool PluralMisuseChecker::MethodCrawler::EndVisitIfStmt(IfStmt *I) { return true; } -bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) { +bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(IfStmt *I) { const Expr *Condition = I->getCond(); if (!Condition) return true; @@ -1350,7 +1350,7 @@ bool PluralMisuseChecker::MethodCrawler::VisitIfStmt(const IfStmt *I) { // Preliminary support for conditional operators. bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator( ConditionalOperator *C) { - RecursiveASTVisitor::TraverseConditionalOperator(C); + DynamicRecursiveASTVisitor::TraverseConditionalOperator(C); MatchingStatements.pop_back(); if (!MatchingStatements.empty()) { if (MatchingStatements.back() != nullptr) @@ -1364,7 +1364,7 @@ bool PluralMisuseChecker::MethodCrawler::TraverseConditionalOperator( } bool PluralMisuseChecker::MethodCrawler::VisitConditionalOperator( - const ConditionalOperator *C) { + ConditionalOperator *C) { const Expr *Condition = C->getCond()->IgnoreParenImpCasts(); if (isCheckingPlurality(Condition)) { MatchingStatements.push_back(C); diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp index 03dab4f7ada7ae0fcecd9a09eb5678f222dfa09f..495502ecaed9464d6bcfe4bc33a1973c4a3a6449 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCMissingSuperCallChecker.cpp @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" -#include "clang/Analysis/PathDiagnostic.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Analysis/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" @@ -38,11 +38,11 @@ struct SelectorDescriptor { // FindSuperCallVisitor - Identify specific calls to the superclass. //===----------------------------------------------------------------------===// -class FindSuperCallVisitor : public RecursiveASTVisitor { +class FindSuperCallVisitor : public DynamicRecursiveASTVisitor { public: explicit FindSuperCallVisitor(Selector S) : DoesCallSuper(false), Sel(S) {} - bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + bool VisitObjCMessageExpr(ObjCMessageExpr *E) override { if (E->getSelector() == Sel) if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) DoesCallSuper = true; diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index 4f35d9442ad9886b90e4889657d7424bc683f6d5..bb882c9d199cea633e7829e310f28b56bc173aab 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Driver/DriverDiagnostic.h" +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -45,16 +45,17 @@ public: // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor : DynamicRecursiveASTVisitor { const PaddingChecker *Checker; - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {} - bool VisitRecordDecl(const RecordDecl *RD) { + explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + } + bool VisitRecordDecl(RecordDecl *RD) override { Checker->visitRecord(RD); return true; } - bool VisitVarDecl(const VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { Checker->visitVariable(VD); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/Taint.cpp b/clang/lib/StaticAnalyzer/Checkers/Taint.cpp index 0bb5739db4b7566f889daa76ed14a7ee09391917..e55d064253b844b89dc3d90ea9be615548270fe1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/Taint.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/Taint.cpp @@ -207,6 +207,14 @@ std::vector taint::getTaintedSymbolsImpl(ProgramStateRef State, return getTaintedSymbolsImpl(State, Sym, Kind, returnFirstOnly); if (const MemRegion *Reg = V.getAsRegion()) return getTaintedSymbolsImpl(State, Reg, Kind, returnFirstOnly); + + if (auto LCV = V.getAs()) { + StoreManager &StoreMgr = State->getStateManager().getStoreManager(); + if (auto DefaultVal = StoreMgr.getDefaultBinding(*LCV)) { + return getTaintedSymbolsImpl(State, *DefaultVal, Kind, returnFirstOnly); + } + } + return {}; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 9d34dfd3cea636b1bed826c713c1c2fabad7144e..b3cd594a0f3529b36c492851c3c464808a439a57 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -142,9 +142,31 @@ bool isASafeCallArg(const Expr *E) { return true; } } + if (isConstOwnerPtrMemberExpr(E)) + return true; // TODO: checker for method calls on non-refcounted objects return isa(E); } +bool isConstOwnerPtrMemberExpr(const clang::Expr *E) { + if (auto *MCE = dyn_cast(E)) { + if (auto *Callee = MCE->getDirectCallee()) { + auto Name = safeGetName(Callee); + if (Name == "get" || Name == "ptr") { + auto *ThisArg = MCE->getImplicitObjectArgument(); + E = ThisArg; + } + } + } + auto *ME = dyn_cast(E); + if (!ME) + return false; + auto *D = ME->getMemberDecl(); + if (!D) + return false; + auto T = D->getType(); + return isOwnerPtrType(T) && T.isConstQualified(); +} + } // namespace clang diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h index e972924e0c523d64275bdd8277d0f7535e1b6dbb..ddbef0fba0448939d7e5e4306a6ba64ad7980d87 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.h @@ -64,6 +64,9 @@ bool tryToFindPtrOrigin( /// \returns Whether \p E is a safe call arugment. bool isASafeCallArg(const clang::Expr *E); +/// \returns true if E is a MemberExpr accessing a const smart pointer type. +bool isConstOwnerPtrMemberExpr(const clang::Expr *E); + /// \returns name of AST node or empty string. template std::string safeGetName(const T *ASTNode) { const auto *const ND = llvm::dyn_cast_or_null(ASTNode); diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 31bebdb07dbdc28b8df923efa49a27f3425f131a..797f3e1f3fba5abb279b25f34a82525e9207d1cd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -145,25 +145,37 @@ bool isCtorOfSafePtr(const clang::FunctionDecl *F) { return isCtorOfRefCounted(F) || isCtorOfCheckedPtr(F); } -bool isSafePtrType(const clang::QualType T) { +template +static bool isPtrOfType(const clang::QualType T, Predicate Pred) { QualType type = T; while (!type.isNull()) { if (auto *elaboratedT = type->getAs()) { type = elaboratedT->desugar(); continue; } - if (auto *specialT = type->getAs()) { - if (auto *decl = specialT->getTemplateName().getAsTemplateDecl()) { - auto name = decl->getNameAsString(); - return isRefType(name) || isCheckedPtr(name); - } + auto *SpecialT = type->getAs(); + if (!SpecialT) return false; - } - return false; + auto *Decl = SpecialT->getTemplateName().getAsTemplateDecl(); + if (!Decl) + return false; + return Pred(Decl->getNameAsString()); } return false; } +bool isSafePtrType(const clang::QualType T) { + return isPtrOfType( + T, [](auto Name) { return isRefType(Name) || isCheckedPtr(Name); }); +} + +bool isOwnerPtrType(const clang::QualType T) { + return isPtrOfType(T, [](auto Name) { + return isRefType(Name) || isCheckedPtr(Name) || Name == "unique_ptr" || + Name == "UniqueRef" || Name == "LazyUniqueRef"; + }); +} + std::optional isUncounted(const QualType T) { if (auto *Subst = dyn_cast(T)) { if (auto *Decl = Subst->getAssociatedDecl()) { @@ -222,7 +234,13 @@ std::optional isUncheckedPtr(const QualType T) { std::optional isUnsafePtr(const QualType T) { if (T->isPointerType() || T->isReferenceType()) { if (auto *CXXRD = T->getPointeeCXXRecordDecl()) { - return isUncounted(CXXRD) || isUnchecked(CXXRD); + auto isUncountedPtr = isUncounted(CXXRD); + auto isUncheckedPtr = isUnchecked(CXXRD); + if (isUncountedPtr && isUncheckedPtr) + return *isUncountedPtr || *isUncheckedPtr; + if (isUncountedPtr) + return *isUncountedPtr; + return isUncheckedPtr; } } return false; @@ -498,6 +516,10 @@ public: if (!Callee) return false; + auto Name = safeGetName(Callee); + if (Name == "ref" || Name == "incrementCheckedPtrCount") + return true; + std::optional IsGetterOfRefCounted = isGetterOfSafePtr(Callee); if (IsGetterOfRefCounted && *IsGetterOfRefCounted) return true; diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h index 7c6c0a63f22aba7bcbd0c3ddc4a5741ae2e6c326..9adfc0f1f5726060d300a516a7387b530df977ec 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h @@ -75,10 +75,18 @@ std::optional isUncountedPtr(const clang::QualType T); /// class, false if not, std::nullopt if inconclusive. std::optional isUncheckedPtr(const clang::QualType T); +/// \returns true if \p T is either a raw pointer or reference to an uncounted +/// or unchecked class, false if not, std::nullopt if inconclusive. +std::optional isUnsafePtr(const QualType T); + /// \returns true if \p T is a RefPtr, Ref, CheckedPtr, CheckedRef, or its /// variant, false if not. bool isSafePtrType(const clang::QualType T); +/// \returns true if \p T is a RefPtr, Ref, CheckedPtr, CheckedRef, or +/// unique_ptr, false if not. +bool isOwnerPtrType(const clang::QualType T); + /// \returns true if \p F creates ref-countable object from uncounted parameter, /// false if not. bool isCtorOfRefCounted(const clang::FunctionDecl *F); diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp index d7f766da6aae066c80f2b29fa2b7d8aa986ba42a..ef2d42ccada65c3c06bb3c3e8ec87e44412fcc6f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefCallArgsChecker.cpp @@ -12,7 +12,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -49,34 +49,31 @@ public: // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { - using Base = RecursiveASTVisitor; - + struct LocalVisitor : DynamicRecursiveASTVisitor { const RawPtrRefCallArgsChecker *Checker; Decl *DeclWithIssue{nullptr}; explicit LocalVisitor(const RawPtrRefCallArgsChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) { + bool TraverseClassTemplateDecl(ClassTemplateDecl *Decl) override { if (isRefType(safeGetName(Decl))) return true; - return Base::TraverseClassTemplateDecl(Decl); + return DynamicRecursiveASTVisitor::TraverseClassTemplateDecl(Decl); } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { llvm::SaveAndRestore SavedDecl(DeclWithIssue); if (D && (isa(D) || isa(D))) DeclWithIssue = D; - return Base::TraverseDecl(D); + return DynamicRecursiveASTVisitor::TraverseDecl(D); } - bool VisitCallExpr(const CallExpr *CE) { + bool VisitCallExpr(CallExpr *CE) override { Checker->visitCallExpr(CE, DeclWithIssue); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp index 06f8f43cee8151fcd5709656d951b9b34c1801b1..e0433c5c2c1a09bf08a258737e3dbc818bfb0c35 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefLocalVarsChecker.cpp @@ -12,8 +12,8 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ParentMapContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -48,17 +48,14 @@ bool isRefcountedStringsHack(const VarDecl *V) { return false; } -struct GuardianVisitor : public RecursiveASTVisitor { - using Base = RecursiveASTVisitor; - +struct GuardianVisitor : DynamicRecursiveASTVisitor { const VarDecl *Guardian{nullptr}; -public: explicit GuardianVisitor(const VarDecl *Guardian) : Guardian(Guardian) { assert(Guardian); } - bool VisitBinaryOperator(const BinaryOperator *BO) { + bool VisitBinaryOperator(BinaryOperator *BO) override { if (BO->isAssignmentOp()) { if (auto *VarRef = dyn_cast(BO->getLHS())) { if (VarRef->getDecl() == Guardian) @@ -68,7 +65,7 @@ public: return true; } - bool VisitCXXConstructExpr(const CXXConstructExpr *CE) { + bool VisitCXXConstructExpr(CXXConstructExpr *CE) override { if (auto *Ctor = CE->getConstructor()) { if (Ctor->isMoveConstructor() && CE->getNumArgs() == 1) { auto *Arg = CE->getArg(0)->IgnoreParenCasts(); @@ -81,7 +78,7 @@ public: return true; } - bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE) { + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *MCE) override { auto MethodName = safeGetName(MCE->getMethodDecl()); if (MethodName == "swap" || MethodName == "leakRef" || MethodName == "releaseNonNull") { @@ -94,7 +91,7 @@ public: return true; } - bool VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE) { + bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *OCE) override { if (OCE->isAssignmentOp()) { assert(OCE->getNumArgs() == 2); auto *ThisArg = OCE->getArg(0)->IgnoreParenCasts(); @@ -184,37 +181,34 @@ public: // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor : DynamicRecursiveASTVisitor { const RawPtrRefLocalVarsChecker *Checker; Decl *DeclWithIssue{nullptr}; TrivialFunctionAnalysis TFA; - using Base = RecursiveASTVisitor; - explicit LocalVisitor(const RawPtrRefLocalVarsChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { llvm::SaveAndRestore SavedDecl(DeclWithIssue); if (D && (isa(D) || isa(D))) DeclWithIssue = D; - return Base::TraverseDecl(D); + return DynamicRecursiveASTVisitor::TraverseDecl(D); } - bool VisitVarDecl(VarDecl *V) { + bool VisitVarDecl(VarDecl *V) override { auto *Init = V->getInit(); if (Init && V->isLocalVarDecl()) Checker->visitVarDecl(V, Init, DeclWithIssue); return true; } - bool VisitBinaryOperator(const BinaryOperator *BO) { + bool VisitBinaryOperator(BinaryOperator *BO) override { if (BO->isAssignmentOp()) { if (auto *VarRef = dyn_cast(BO->getLHS())) { if (auto *V = dyn_cast(VarRef->getDecl())) @@ -224,33 +218,33 @@ public: return true; } - bool TraverseIfStmt(IfStmt *IS) { + bool TraverseIfStmt(IfStmt *IS) override { if (!TFA.isTrivial(IS)) - return Base::TraverseIfStmt(IS); + return DynamicRecursiveASTVisitor::TraverseIfStmt(IS); return true; } - bool TraverseForStmt(ForStmt *FS) { + bool TraverseForStmt(ForStmt *FS) override { if (!TFA.isTrivial(FS)) - return Base::TraverseForStmt(FS); + return DynamicRecursiveASTVisitor::TraverseForStmt(FS); return true; } - bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) { + bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) override { if (!TFA.isTrivial(FRS)) - return Base::TraverseCXXForRangeStmt(FRS); + return DynamicRecursiveASTVisitor::TraverseCXXForRangeStmt(FRS); return true; } - bool TraverseWhileStmt(WhileStmt *WS) { + bool TraverseWhileStmt(WhileStmt *WS) override { if (!TFA.isTrivial(WS)) - return Base::TraverseWhileStmt(WS); + return DynamicRecursiveASTVisitor::TraverseWhileStmt(WS); return true; } - bool TraverseCompoundStmt(CompoundStmt *CS) { + bool TraverseCompoundStmt(CompoundStmt *CS) override { if (!TFA.isTrivial(CS)) - return Base::TraverseCompoundStmt(CS); + return DynamicRecursiveASTVisitor::TraverseCompoundStmt(CS); return true; } }; @@ -281,6 +275,9 @@ public: if (isa(InitArgOrigin)) return true; + if (isConstOwnerPtrMemberExpr(InitArgOrigin)) + return true; + if (auto *Ref = llvm::dyn_cast(InitArgOrigin)) { if (auto *MaybeGuardian = dyn_cast_or_null(Ref->getFoundDecl())) { diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp index 2ce6bc330e0ca13e10addc52dd7428eab00cd236..d7e5ebee9a9b4fe4bc298b9e50a73be2e2a85014 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp @@ -12,7 +12,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -48,17 +48,16 @@ public: // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor : DynamicRecursiveASTVisitor { const RawPtrRefMemberChecker *Checker; explicit LocalVisitor(const RawPtrRefMemberChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool VisitRecordDecl(const RecordDecl *RD) { + bool VisitRecordDecl(RecordDecl *RD) override { Checker->visitRecordDecl(RD); return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp index e80246f49a3100a415bb666346fc3e852d06887e..77520f1f731c1fee0f1c4a6fc8f7beeb141c0d69 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp @@ -10,7 +10,7 @@ #include "DiagOutputUtils.h" #include "PtrTypesSemantics.h" #include "clang/AST/CXXInheritance.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" @@ -173,17 +173,16 @@ public: // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor : DynamicRecursiveASTVisitor { const RefCntblBaseVirtualDtorChecker *Checker; explicit LocalVisitor(const RefCntblBaseVirtualDtorChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } - - bool VisitCXXRecordDecl(const CXXRecordDecl *RD) { + bool VisitCXXRecordDecl(CXXRecordDecl *RD) override { if (!RD->hasDefinition()) return true; diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp index 998bd4ccee07dbbbc9da516f325195e6e2d70f71..3fb763e72e6809cc666a19fc28b10f2368768c16 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp @@ -6,10 +6,11 @@ // //===----------------------------------------------------------------------===// +#include "ASTUtils.h" #include "DiagOutputUtils.h" #include "PtrTypesSemantics.h" #include "clang/AST/CXXInheritance.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" @@ -26,6 +27,7 @@ private: BugType Bug{this, "Lambda capture of uncounted variable", "WebKit coding guidelines"}; mutable BugReporter *BR = nullptr; + TrivialFunctionAnalysis TFA; public: void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR, @@ -35,42 +37,130 @@ public: // The calls to checkAST* from AnalysisConsumer don't // visit template instantiations or lambda classes. We // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { + struct LocalVisitor : DynamicRecursiveASTVisitor { const UncountedLambdaCapturesChecker *Checker; + llvm::DenseSet DeclRefExprsToIgnore; + QualType ClsType; + explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker) : Checker(Checker) { assert(Checker); + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = false; + } + + bool TraverseCXXMethodDecl(CXXMethodDecl *CXXMD) override { + llvm::SaveAndRestore SavedDecl(ClsType); + ClsType = CXXMD->getThisType(); + return DynamicRecursiveASTVisitor::TraverseCXXMethodDecl(CXXMD); + } + + bool shouldCheckThis() { + auto result = !ClsType.isNull() ? isUnsafePtr(ClsType) : std::nullopt; + return result && *result; + } + + bool VisitDeclRefExpr(DeclRefExpr *DRE) override { + if (DeclRefExprsToIgnore.contains(DRE)) + return true; + auto *VD = dyn_cast_or_null(DRE->getDecl()); + if (!VD) + return true; + auto *Init = VD->getInit(); + if (!Init) + return true; + auto *L = dyn_cast_or_null(Init->IgnoreParenCasts()); + if (!L) + return true; + Checker->visitLambdaExpr(L, shouldCheckThis()); + return true; } - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return false; } + // WTF::switchOn(T, F... f) is a variadic template function and couldn't + // be annotated with NOESCAPE. We hard code it here to workaround that. + bool shouldTreatAllArgAsNoEscape(FunctionDecl *Decl) { + auto *NsDecl = Decl->getParent(); + if (!NsDecl || !isa(NsDecl)) + return false; + return safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn"; + } - bool VisitLambdaExpr(LambdaExpr *L) { - Checker->visitLambdaExpr(L); + bool VisitCallExpr(CallExpr *CE) override { + checkCalleeLambda(CE); + if (auto *Callee = CE->getDirectCallee()) { + bool TreatAllArgsAsNoEscape = shouldTreatAllArgAsNoEscape(Callee); + unsigned ArgIndex = 0; + for (auto *Param : Callee->parameters()) { + if (ArgIndex >= CE->getNumArgs()) + return true; + auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts(); + if (!Param->hasAttr() && !TreatAllArgsAsNoEscape) { + if (auto *L = dyn_cast_or_null(Arg)) { + Checker->visitLambdaExpr(L, shouldCheckThis()); + } + } + ++ArgIndex; + } + } return true; } + + void checkCalleeLambda(CallExpr *CE) { + auto *Callee = CE->getCallee(); + if (!Callee) + return; + auto *DRE = dyn_cast(Callee->IgnoreParenCasts()); + if (!DRE) + return; + auto *MD = dyn_cast_or_null(DRE->getDecl()); + if (!MD || CE->getNumArgs() != 1) + return; + auto *Arg = CE->getArg(0)->IgnoreParenCasts(); + auto *ArgRef = dyn_cast(Arg); + if (!ArgRef) + return; + auto *VD = dyn_cast_or_null(ArgRef->getDecl()); + if (!VD) + return; + auto *Init = VD->getInit(); + if (!Init) + return; + auto *L = dyn_cast_or_null(Init->IgnoreParenCasts()); + if (!L) + return; + DeclRefExprsToIgnore.insert(ArgRef); + Checker->visitLambdaExpr(L, shouldCheckThis(), + /* ignoreParamVarDecl */ true); + } }; LocalVisitor visitor(this); visitor.TraverseDecl(const_cast(TUD)); } - void visitLambdaExpr(LambdaExpr *L) const { + void visitLambdaExpr(LambdaExpr *L, bool shouldCheckThis, + bool ignoreParamVarDecl = false) const { + if (TFA.isTrivial(L->getBody())) + return; for (const LambdaCapture &C : L->captures()) { if (C.capturesVariable()) { ValueDecl *CapturedVar = C.getCapturedVar(); + if (ignoreParamVarDecl && isa(CapturedVar)) + continue; QualType CapturedVarQualType = CapturedVar->getType(); - if (auto *CapturedVarType = CapturedVarQualType.getTypePtrOrNull()) { - auto IsUncountedPtr = isUncountedPtr(CapturedVarQualType); - if (IsUncountedPtr && *IsUncountedPtr) - reportBug(C, CapturedVar, CapturedVarType); - } + auto IsUncountedPtr = isUnsafePtr(CapturedVar->getType()); + if (IsUncountedPtr && *IsUncountedPtr) + reportBug(C, CapturedVar, CapturedVarQualType); + } else if (C.capturesThis() && shouldCheckThis) { + if (ignoreParamVarDecl) // this is always a parameter to this function. + continue; + reportBugOnThisPtr(C); } } } void reportBug(const LambdaCapture &Capture, ValueDecl *CapturedVar, - const Type *T) const { + const QualType T) const { assert(CapturedVar); SmallString<100> Buf; @@ -89,7 +179,25 @@ public: } printQuotedQualifiedName(Os, Capture.getCapturedVar()); - Os << " to uncounted type is unsafe."; + Os << " to ref-counted type or CheckedPtr-capable type is unsafe."; + + PathDiagnosticLocation BSLoc(Capture.getLocation(), BR->getSourceManager()); + auto Report = std::make_unique(Bug, Os.str(), BSLoc); + BR->emitReport(std::move(Report)); + } + + void reportBugOnThisPtr(const LambdaCapture &Capture) const { + SmallString<100> Buf; + llvm::raw_svector_ostream Os(Buf); + + if (Capture.isExplicit()) { + Os << "Captured "; + } else { + Os << "Implicitly captured "; + } + + Os << "raw-pointer 'this' to ref-counted type or CheckedPtr-capable type " + "is unsafe."; PathDiagnosticLocation BSLoc(Capture.getLocation(), BR->getSourceManager()); auto Report = std::make_unique(Bug, Os.str(), BSLoc); diff --git a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp index 84004b8e5c1cdb8ff2a379f06a24b4d977a181b7..05c99c4a844e9e60006c6a1379d72f75f189562b 100644 --- a/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugSuppression.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/BugReporter/BugSuppression.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" using namespace clang; @@ -76,13 +76,13 @@ inline bool fullyContains(SourceRange Larger, SourceRange Smaller, isLessOrEqual(Smaller.getEnd(), Larger.getEnd(), SM); } -class CacheInitializer : public RecursiveASTVisitor { +class CacheInitializer : public DynamicRecursiveASTVisitor { public: static void initialize(const Decl *D, Ranges &ToInit) { CacheInitializer(ToInit).TraverseDecl(const_cast(D)); } - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { // Bug location could be somewhere in the init value of // a freshly declared variable. Even though it looks like the // user applied attribute to a statement, it will apply to a @@ -90,7 +90,7 @@ public: return VisitAttributedNode(D); } - bool VisitAttributedStmt(AttributedStmt *AS) { + bool VisitAttributedStmt(AttributedStmt *AS) override { // When we apply attributes to statements, it actually creates // a wrapper statement that only contains attributes and the wrapped // statement. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 5ff692ef562d693d320f3d89f12e0cc70a919e76..5650bf4b636333b26b9982aa89629072d14dea53 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1842,6 +1842,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::CapturedStmtClass: case Stmt::OpenACCComputeConstructClass: case Stmt::OpenACCLoopConstructClass: + case Stmt::OpenACCCombinedConstructClass: case Stmt::OMPUnrollDirectiveClass: case Stmt::OMPMetaDirectiveClass: case Stmt::HLSLOutArgExprClass: { diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index ccc3097e8d2f971cfe092c3c5deae2176634a79f..f7020da2e6da20092ce690b4f60f3a347dffdc13 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -45,7 +45,7 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, const CallEvent &Call) { SVal ThisVal; bool AlwaysReturnsLValue; - const CXXRecordDecl *ThisRD = nullptr; + [[maybe_unused]] const CXXRecordDecl *ThisRD = nullptr; if (const CXXConstructorCall *Ctor = dyn_cast(&Call)) { assert(Ctor->getDecl()->isTrivial()); assert(Ctor->getDecl()->isCopyOrMoveConstructor()); @@ -68,23 +68,15 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, Bldr.takeNodes(Pred); assert(ThisRD); - if (!ThisRD->isEmpty()) { - // Load the source value only for non-empty classes. - // Otherwise it'd retrieve an UnknownVal - // and bind it and RegionStore would think that the actual value - // in this region at this offset is unknown. - SVal V = Call.getArgSVal(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()); - evalBind(Dst, CallExpr, Pred, ThisVal, V, true); - } else { - Dst.Add(Pred); - } + SVal V = Call.getArgSVal(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()); + evalBind(Dst, CallExpr, Pred, ThisVal, V, true); PostStmt PS(CallExpr, LCtx); for (ExplodedNode *N : Dst) { diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 674099dd7e1f0f675924dc600b55ca0b61ac4db1..46e294a1741cfe7a902abe189169b61593c88964 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -67,9 +67,10 @@ private: isa(r)) && "Not a base"); } -public: +public: bool isDirect() const { return P.getInt() & Direct; } + bool isDefault() const { return !isDirect(); } bool hasSymbolicOffset() const { return P.getInt() & Symbolic; } const MemRegion *getRegion() const { return P.getPointer(); } @@ -232,27 +233,86 @@ public: void printJson(raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0, bool IsDot = false) const { - for (iterator I = begin(), E = end(); I != E; ++I) { - // TODO: We might need a .printJson for I.getKey() as well. + using namespace llvm; + DenseMap StringifyCache; + auto ToString = [&StringifyCache](const MemRegion *R) { + auto [Place, Inserted] = StringifyCache.try_emplace(R); + if (!Inserted) + return Place->second; + std::string Res; + raw_string_ostream OS(Res); + OS << R; + Place->second = Res; + return Res; + }; + + using Cluster = + std::pair>; + using Binding = std::pair; + + const auto MemSpaceBeforeRegionName = [&ToString](const Cluster *L, + const Cluster *R) { + if (isa(L->first) && !isa(R->first)) + return true; + if (!isa(L->first) && isa(R->first)) + return false; + return ToString(L->first) < ToString(R->first); + }; + + const auto SymbolicBeforeOffset = [&ToString](const BindingKey &L, + const BindingKey &R) { + if (L.hasSymbolicOffset() && !R.hasSymbolicOffset()) + return true; + if (!L.hasSymbolicOffset() && R.hasSymbolicOffset()) + return false; + if (L.hasSymbolicOffset() && R.hasSymbolicOffset()) + return ToString(L.getRegion()) < ToString(R.getRegion()); + return L.getOffset() < R.getOffset(); + }; + + const auto DefaultBindingBeforeDirectBindings = + [&SymbolicBeforeOffset](const Binding *LPtr, const Binding *RPtr) { + const BindingKey &L = LPtr->first; + const BindingKey &R = RPtr->first; + if (L.isDefault() && !R.isDefault()) + return true; + if (!L.isDefault() && R.isDefault()) + return false; + assert(L.isDefault() == R.isDefault()); + return SymbolicBeforeOffset(L, R); + }; + + const auto AddrOf = [](const auto &Item) { return &Item; }; + + std::vector SortedClusters; + SortedClusters.reserve(std::distance(begin(), end())); + append_range(SortedClusters, map_range(*this, AddrOf)); + llvm::sort(SortedClusters, MemSpaceBeforeRegionName); + + for (auto [Idx, C] : llvm::enumerate(SortedClusters)) { + const auto &[BaseRegion, Bindings] = *C; Indent(Out, Space, IsDot) - << "{ \"cluster\": \"" << I.getKey() << "\", \"pointer\": \"" - << (const void *)I.getKey() << "\", \"items\": [" << NL; + << "{ \"cluster\": \"" << BaseRegion << "\", \"pointer\": \"" + << (const void *)BaseRegion << "\", \"items\": [" << NL; + + std::vector SortedBindings; + SortedBindings.reserve(std::distance(Bindings.begin(), Bindings.end())); + append_range(SortedBindings, map_range(Bindings, AddrOf)); + llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings); ++Space; - const ClusterBindings &CB = I.getData(); - for (ClusterBindings::iterator CI = CB.begin(), CE = CB.end(); CI != CE; - ++CI) { - Indent(Out, Space, IsDot) << "{ " << CI.getKey() << ", \"value\": "; - CI.getData().printJson(Out, /*AddQuotes=*/true); + for (auto [Idx, B] : llvm::enumerate(SortedBindings)) { + const auto &[Key, Value] = *B; + Indent(Out, Space, IsDot) << "{ " << Key << ", \"value\": "; + Value.printJson(Out, /*AddQuotes=*/true); Out << " }"; - if (std::next(CI) != CE) + if (Idx != SortedBindings.size() - 1) Out << ','; Out << NL; } - --Space; Indent(Out, Space, IsDot) << "]}"; - if (std::next(I) != E) + if (Idx != SortedClusters.size() - 1) Out << ','; Out << NL; } @@ -548,6 +608,9 @@ public: // Part of public interface to class. return getBinding(getRegionBindings(S), L, T); } + std::optional + getUniqueDefaultBinding(nonloc::LazyCompoundVal LCV) const; + std::optional getDefaultBinding(Store S, const MemRegion *R) override { RegionBindingsRef B = getRegionBindings(S); // Default bindings are always applied over a base region so look up the @@ -2276,20 +2339,16 @@ NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B, return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R); } -static bool isRecordEmpty(const RecordDecl *RD) { - if (!RD->field_empty()) - return false; - if (const CXXRecordDecl *CRD = dyn_cast(RD)) - return CRD->getNumBases() == 0; - return true; -} - SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R) { const RecordDecl *RD = R->getValueType()->castAs()->getDecl(); - if (!RD->getDefinition() || isRecordEmpty(RD)) + if (!RD->getDefinition()) return UnknownVal(); + // We also create a LCV for copying empty structs because then the store + // behavior doesn't depend on the struct layout. + // This way even an empty struct can carry taint, no matter if creduce drops + // the last field member or not. return createLazyBinding(B, R); } @@ -2549,9 +2608,43 @@ RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B, return NewB; } +std::optional +RegionStoreManager::getUniqueDefaultBinding(nonloc::LazyCompoundVal LCV) const { + const MemRegion *BaseR = LCV.getRegion(); + + // We only handle base regions. + if (BaseR != BaseR->getBaseRegion()) + return std::nullopt; + + const auto *Cluster = getRegionBindings(LCV.getStore()).lookup(BaseR); + if (!Cluster || !llvm::hasSingleElement(*Cluster)) + return std::nullopt; + + const auto [Key, Value] = *Cluster->begin(); + return Key.isDirect() ? std::optional{} : Value; +} + std::optional RegionStoreManager::tryBindSmallStruct( RegionBindingsConstRef B, const TypedValueRegion *R, const RecordDecl *RD, nonloc::LazyCompoundVal LCV) { + // If we try to copy a Conjured value representing the value of the whole + // struct, don't try to element-wise copy each field. + // That would unnecessarily bind Derived symbols slicing off the subregion for + // the field from the whole Conjured symbol. + // + // struct Window { int width; int height; }; + // Window getWindow(); <-- opaque fn. + // Window w = getWindow(); <-- conjures a new Window. + // Window w2 = w; <-- trivial copy "w", calling "tryBindSmallStruct" + // + // We should not end up with a new Store for "w2" like this: + // Direct [ 0..31]: Derived{Conj{}, w.width} + // Direct [32..63]: Derived{Conj{}, w.height} + // Instead, we should just bind that Conjured value instead. + if (std::optional Val = getUniqueDefaultBinding(LCV)) { + return B.addBinding(BindingKey::Make(R, BindingKey::Default), Val.value()); + } + FieldVector Fields; if (const CXXRecordDecl *Class = dyn_cast(RD)) diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 03bc40804d73287319326af9a981e8bc8f4331af..91c9b085f68292b7f3b1ddaca82b01b2727f5469 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -15,7 +15,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CallGraph.h" @@ -68,7 +68,7 @@ STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function."); namespace { class AnalysisConsumer : public AnalysisASTConsumer, - public RecursiveASTVisitor { + public DynamicRecursiveASTVisitor { enum { AM_None = 0, AM_Syntax = 0x1, @@ -147,6 +147,9 @@ public: if (Opts.ShouldDisplayMacroExpansions) MacroExpansions.registerForPreprocessor(PP); + + // Visitor options. + ShouldWalkTypesOfTypeLocs = false; } ~AnalysisConsumer() override { @@ -261,11 +264,8 @@ public: ExprEngine::InliningModes IMode, SetOfConstDecls *VisitedCallees); - /// Visitors for the RecursiveASTVisitor. - bool shouldWalkTypesOfTypeLocs() const { return false; } - /// Handle callbacks for arbitrary Decls. - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { AnalysisMode Mode = getModeForDecl(D, RecVisitorMode); if (Mode & AM_Syntax) { if (SyntaxCheckTimer) @@ -277,7 +277,7 @@ public: return true; } - bool VisitVarDecl(VarDecl *VD) { + bool VisitVarDecl(VarDecl *VD) override { if (!Opts.IsNaiveCTUEnabled) return true; @@ -306,7 +306,7 @@ public: return true; } - bool VisitFunctionDecl(FunctionDecl *FD) { + bool VisitFunctionDecl(FunctionDecl *FD) override { IdentifierInfo *II = FD->getIdentifier(); if (II && II->getName().starts_with("__inline")) return true; @@ -321,7 +321,7 @@ public: return true; } - bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { + bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override { if (MD->isThisDeclarationADefinition()) { assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); HandleCode(MD, RecVisitorMode); @@ -329,7 +329,7 @@ public: return true; } - bool VisitBlockDecl(BlockDecl *BD) { + bool VisitBlockDecl(BlockDecl *BD) override { if (BD->hasBody()) { assert(RecVisitorMode == AM_Syntax || Mgr->shouldInlineCall() == false); // Since we skip function template definitions, we should skip blocks diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp index ae11fbbe32b7627fa7e359fa0b6b1a9c5b56cf77..168c73df393ffae5e5e5b365ce3016d3002c3293 100644 --- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -78,6 +78,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { CompilerInstance Instance(CI.getPCHContainerOperations()); Instance.setInvocation(std::move(Invocation)); Instance.createDiagnostics( + CI.getVirtualFileSystem(), new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), /*ShouldOwnClient=*/true); diff --git a/clang/lib/Testing/TestAST.cpp b/clang/lib/Testing/TestAST.cpp index fe8b93851613dd3aa0b8289fcce0ab27c456a033..f7348aa068c51ba4c94ffcfd7b9ab15391ffdd2c 100644 --- a/clang/lib/Testing/TestAST.cpp +++ b/clang/lib/Testing/TestAST.cpp @@ -55,7 +55,7 @@ public: // Provides "empty" ASTContext etc if we fail before parsing gets started. void createMissingComponents(CompilerInstance &Clang) { if (!Clang.hasDiagnostics()) - Clang.createDiagnostics(); + Clang.createDiagnostics(*llvm::vfs::getRealFileSystem()); if (!Clang.hasFileManager()) Clang.createFileManager(); if (!Clang.hasSourceManager()) @@ -82,9 +82,24 @@ TestAST::TestAST(const TestInputs &In) { auto RecoverFromEarlyExit = llvm::make_scope_exit([&] { createMissingComponents(*Clang); }); + std::string Filename = In.FileName; + if (Filename.empty()) + Filename = getFilenameForTesting(In.Language).str(); + + // Set up a VFS with only the virtual file visible. + auto VFS = llvm::makeIntrusiveRefCnt(); + if (auto Err = VFS->setCurrentWorkingDirectory(In.WorkingDir)) + ADD_FAILURE() << "Failed to setWD: " << Err.message(); + VFS->addFile(Filename, /*ModificationTime=*/0, + llvm::MemoryBuffer::getMemBufferCopy(In.Code, Filename)); + for (const auto &Extra : In.ExtraFiles) + VFS->addFile( + Extra.getKey(), /*ModificationTime=*/0, + llvm::MemoryBuffer::getMemBufferCopy(Extra.getValue(), Extra.getKey())); + // Extra error conditions are reported through diagnostics, set that up first. bool ErrorOK = In.ErrorOK || llvm::StringRef(In.Code).contains("error-ok"); - Clang->createDiagnostics(new StoreDiagnostics(Diagnostics, !ErrorOK)); + Clang->createDiagnostics(*VFS, new StoreDiagnostics(Diagnostics, !ErrorOK)); // Parse cc1 argv, (typically [-std=c++20 input.cc]) into CompilerInvocation. std::vector Argv; @@ -93,9 +108,6 @@ TestAST::TestAST(const TestInputs &In) { Argv.push_back(S.c_str()); for (const auto &S : In.ExtraArgs) Argv.push_back(S.c_str()); - std::string Filename = In.FileName; - if (Filename.empty()) - Filename = getFilenameForTesting(In.Language).str(); Argv.push_back(Filename.c_str()); Clang->setInvocation(std::make_unique()); if (!CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, @@ -105,16 +117,6 @@ TestAST::TestAST(const TestInputs &In) { } assert(!Clang->getInvocation().getFrontendOpts().DisableFree); - // Set up a VFS with only the virtual file visible. - auto VFS = llvm::makeIntrusiveRefCnt(); - if (auto Err = VFS->setCurrentWorkingDirectory(In.WorkingDir)) - ADD_FAILURE() << "Failed to setWD: " << Err.message(); - VFS->addFile(Filename, /*ModificationTime=*/0, - llvm::MemoryBuffer::getMemBufferCopy(In.Code, Filename)); - for (const auto &Extra : In.ExtraFiles) - VFS->addFile( - Extra.getKey(), /*ModificationTime=*/0, - llvm::MemoryBuffer::getMemBufferCopy(Extra.getValue(), Extra.getKey())); Clang->createFileManager(VFS); // Running the FrontendAction creates the other components: SourceManager, diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index fd1b7af0600da77f73dfcd2ae124c0986a4c5e67..5a648df05e4fd33aeb32431621db0f1e9eca6f85 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -322,7 +322,8 @@ public: // Create the compiler's actual diagnostics engine. sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); - ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); + ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(), + DiagConsumer, /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; @@ -650,7 +651,7 @@ bool DependencyScanningWorker::computeDependencies( auto DiagOpts = CreateAndPopulateDiagOpts(FinalCCommandLine); sanitizeDiagOpts(*DiagOpts); IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(DiagOpts.release(), &DC, + CompilerInstance::createDiagnostics(*FinalFS, DiagOpts.release(), &DC, /*ShouldOwnClient=*/false); // Although `Diagnostics` are used only for command-line parsing, the diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index ffacf9cf1f78293a4a500cfc6d8f5d60ce4aa818..88b7349ce8fed688e1d4e6a9b4ce689d1749479b 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -387,7 +387,8 @@ bool ToolInvocation::run() { TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DiagOpts); IntrusiveRefCntPtr Diagnostics = CompilerInstance::createDiagnostics( - &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); + Files->getVirtualFileSystem(), &*DiagOpts, + DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); // Although `Diagnostics` are used only for command-line parsing, the custom // `DiagConsumer` might expect a `SourceManager` to be present. SourceManager SrcMgr(*Diagnostics, *Files); @@ -456,7 +457,8 @@ bool FrontendActionFactory::runInvocation( std::unique_ptr ScopedToolAction(create()); // Create the compiler's actual diagnostics engine. - Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); + Compiler.createDiagnostics(Files->getVirtualFileSystem(), DiagConsumer, + /*ShouldOwnClient=*/false); if (!Compiler.hasDiagnostics()) return false; @@ -652,7 +654,8 @@ public: DiagnosticConsumer *DiagConsumer) override { std::unique_ptr AST = ASTUnit::LoadFromCompilerInvocation( Invocation, std::move(PCHContainerOps), - CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(), + CompilerInstance::createDiagnostics(Files->getVirtualFileSystem(), + &Invocation->getDiagnosticOpts(), DiagConsumer, /*ShouldOwnClient=*/false), Files); diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes index f4f9c7a244e0a3bc91523b2591a605ff898f3554..c5171e2f287d2896efd9aee49b8dae1b72dec453 100644 --- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes @@ -13,3 +13,7 @@ Tags: SwiftConformsTo: MySwiftModule.MySwiftNonCopyableProtocol - Name: CopyableType SwiftCopyable: true +- Name: NonEscapableType + SwiftEscapable: false +- Name: EscapableType + SwiftEscapable: true diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h index a8f6d0248eae4055e5e3e49e00e371aa0d9e3aeb..f205cd3c6e7b71959cc1764631b898d8b3198834 100644 --- a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h @@ -7,3 +7,6 @@ inline void RCRelease(RefCountedType *x) { x->value--; } struct NonCopyableType { int value; }; struct CopyableType { int value; }; + +struct NonEscapableType { int value; }; +struct EscapableType { int value; }; diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp index 6457e1557618deb6d9bc581ac254ebab41c6eb54..d0e7e31fc1d726608cd23e4930863588e005eb68 100644 --- a/clang/test/APINotes/swift-import-as.cpp +++ b/clang/test/APINotes/swift-import-as.cpp @@ -4,6 +4,8 @@ // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonCopyableType | FileCheck -check-prefix=CHECK-NON-COPYABLE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter CopyableType | FileCheck -check-prefix=CHECK-COPYABLE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter NonEscapableType | FileCheck -check-prefix=CHECK-NON-ESCAPABLE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter EscapableType | FileCheck -check-prefix=CHECK-ESCAPABLE %s #include @@ -26,3 +28,11 @@ // CHECK-COPYABLE: Dumping CopyableType: // CHECK-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct CopyableType // CHECK-COPYABLE-NOT: SwiftAttrAttr + +// CHECK-NON-ESCAPABLE: Dumping NonEscapableType: +// CHECK-NON-ESCAPABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonEscapableType +// CHECK-NON-ESCAPABLE: SwiftAttrAttr {{.+}} "~Escapable" + +// CHECK-ESCAPABLE: Dumping EscapableType: +// CHECK-ESCAPABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct EscapableType +// CHECK-ESCAPABLE: SwiftAttrAttr {{.+}} "Escapable" diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp index 7d1fcbda10965f7d6d1696fda82119c7ce6cfb7d..3c6cd0aa36e7fe185f15045549e118404f86a20f 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -145,6 +145,17 @@ namespace Fail { // both-note {{initializer of 'a' is not a constant expression}} } +namespace ToPtr { + struct S { + const int *p = nullptr; + }; + struct P { + const int *p; // both-note {{invalid type 'const int *' is a member of 'ToPtr::P'}} + }; + constexpr P p = __builtin_bit_cast(P, S{}); // both-error {{must be initialized by a constant expression}} \ + // both-note {{bit_cast to a pointer type is not allowed in a constant expression}} +} + namespace NullPtr { constexpr nullptr_t N = __builtin_bit_cast(nullptr_t, (intptr_t)1u); static_assert(N == nullptr); @@ -496,7 +507,7 @@ typedef bool bool32 __attribute__((ext_vector_type(32))); typedef bool bool128 __attribute__((ext_vector_type(128))); static_assert(bit_cast(bool8{1,0,1,0,1,0,1,0}) == (LITTLE_END ? 0x55 : 0xAA), ""); -constexpr bool8 b8 = __builtin_bit_cast(bool8, 0x55); // both-error {{__builtin_bit_cast source size does not equal destination size (4 vs 1)}} +constexpr bool8 b8 = __builtin_bit_cast(bool8, 0x55); // both-error {{'__builtin_bit_cast' source type 'int' does not match destination type 'bool8' (vector of 8 'bool' values) (4 vs 1 bytes)}} #if 0 static_assert(check_round_trip(static_cast(0)), ""); static_assert(check_round_trip(static_cast(1)), ""); @@ -535,5 +546,5 @@ namespace test_complex { static_assert(TF.A == 1.0f && TF.B == 2.0f); constexpr double D = __builtin_bit_cast(double, test_float_complex); - constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{__builtin_bit_cast source size does not equal destination size}} + constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{size of '__builtin_bit_cast' source type 'const _Complex unsigned int' does not match destination type 'int' (8 vs 4 bytes)}} } diff --git a/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl index 5a13ca7735f999598924f9288118172301b572f4..8c951e9829211433fac58d8a15f1123e63db06e3 100644 --- a/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/AppendStructuredBuffer-AST.hlsl @@ -30,20 +30,20 @@ AppendStructuredBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class AppendStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer -// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' // CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &(unsigned int)' // CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <> class AppendStructuredBuffer definition // CHECK: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]] diff --git a/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl index b75f3fcb959cfc82c2a702352a7704de1e21782a..86e3d387883dcc674331e1dea471043cab295ff3 100644 --- a/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/ConsumeStructuredBuffer-AST.hlsl @@ -30,13 +30,13 @@ ConsumeStructuredBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class ConsumeStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer -// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' // CHECK-NOT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &(unsigned int)' // CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <> class ConsumeStructuredBuffer definition @@ -44,7 +44,7 @@ ConsumeStructuredBuffer Buffer; // CHECK: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]] diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl index ebddd72ddb1e0eda7752e52c2928be8076ee9fa7..f2eba75481fd5521259179e847f6dc2415ab2058 100644 --- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl @@ -29,12 +29,12 @@ RWBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer -// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' // CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' // CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> // CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> @@ -55,7 +55,7 @@ RWBuffer Buffer; // CHECK: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t -// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer diff --git a/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl index 4a1e1d7570e5e9949e197b4866f9105fbe16ce5d..cc10b41b7c2b0dd7edf0990d82a5a88baad8a552 100644 --- a/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWStructuredBuffer-AST.hlsl @@ -30,13 +30,13 @@ RWStructuredBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer -// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' // CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' // CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> // CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> @@ -57,7 +57,7 @@ RWStructuredBuffer Buffer; // CHECK: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]] diff --git a/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl index f334e1bb6db3fc3427830104cc77c09689121136..1aac67b5ced5bc90207eb6ffa193d43dce9a189e 100644 --- a/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RasterizerOrderedStructuredBuffer-AST.hlsl @@ -30,14 +30,14 @@ RasterizerOrderedStructuredBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RasterizerOrderedStructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::is_rov]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] -// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer +// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer -// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' // CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' // CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> // CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> @@ -58,9 +58,9 @@ RasterizerOrderedStructuredBuffer Buffer; // CHECK: TemplateArgument type 'int' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::is_rov]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]] -// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer +// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer diff --git a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl index 521c3d45b20225ee948a51d56ff9c3346841306a..95ae20ead32bfebb7afae3728daa6ce105259502 100644 --- a/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffer-AST.hlsl @@ -30,13 +30,13 @@ StructuredBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class StructuredBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit RawBuffer -// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' +// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'const element_type &(unsigned int) const' // CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' // CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <> // CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <> @@ -57,7 +57,7 @@ StructuredBuffer Buffer; // CHECK: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h '__hlsl_resource_t +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] // CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] diff --git a/clang/test/AST/arm-mfp8.cpp b/clang/test/AST/arm-mfp8.cpp index 51bebba067eb9f60154be3be79f2df589b6d018c..195c734fc753e5c913e1353553ef8f1a6295907d 100644 --- a/clang/test/AST/arm-mfp8.cpp +++ b/clang/test/AST/arm-mfp8.cpp @@ -5,7 +5,6 @@ /* Various contexts where type __mfp8 can appear. */ -#include /* Namespace */ namespace { __mfp8 f2n; @@ -13,7 +12,7 @@ namespace { } //CHECK: |-NamespaceDecl {{.*}} -//CHECK-NEXT: | |-VarDecl {{.*}} f2n '__mfp8':'__MFloat8_t' +//CHECK-NEXT: | |-VarDecl {{.*}} f2n '__mfp8' //CHECK-NEXT: | `-VarDecl {{.*}} arr1n '__mfp8[10]' @@ -24,14 +23,14 @@ namespace { return f1n; } //CHECK: |-FunctionDecl {{.*}} func1n 'const __mfp8 (const __mfp8)' -//CHECK: | `-VarDecl {{.*}} f1n '__mfp8':'__MFloat8_t' -//CHECK-NEXT: |-BinaryOperator {{.*}} '__mfp8':'__MFloat8_t' lvalue '=' -//CHECK-NEXT: | |-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue Var {{.*}} 'f1n' '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'const __mfp8':'const __MFloat8_t' lvalue ParmVar {{.*}} 'mfp8' 'const __mfp8':'const __MFloat8_t' +//CHECK: | `-VarDecl {{.*}} f1n '__mfp8' +//CHECK-NEXT: |-BinaryOperator {{.*}} '__mfp8' lvalue '=' +//CHECK-NEXT: | |-DeclRefExpr {{.*}} '__mfp8' lvalue Var {{.*}} 'f1n' '__mfp8' +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} 'const __mfp8' lvalue ParmVar {{.*}} 'mfp8' 'const __mfp8' //CHECK-NEXT: `-ReturnStmt {{.*}} -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' -//CHECK-NEXT: `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue Var {{.*}} 'f1n' '__mfp8':'__MFloat8_t' +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '__mfp8' +//CHECK-NEXT: `-DeclRefExpr {{.*}} '__mfp8' lvalue Var {{.*}} 'f1n' '__mfp8' /* Class */ @@ -39,7 +38,7 @@ namespace { class C1 { __mfp8 f1c; static const __mfp8 f2c; - volatile __MFloat8_t f3c; + volatile __mfp8 f3c; public: C1(__mfp8 arg) : f1c(arg), f3c(arg) { } __mfp8 func1c(__mfp8 arg ) { @@ -51,31 +50,31 @@ public: }; //CHECK: | |-CXXRecordDecl {{.*}} referenced class C1 -//CHECK-NEXT: | |-FieldDecl {{.*}} f1c '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | |-VarDecl {{.*}} f2c 'const __mfp8':'const __MFloat8_t' static -//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile __MFloat8_t' +//CHECK-NEXT: | |-FieldDecl {{.*}} f1c '__mfp8' +//CHECK-NEXT: | |-VarDecl {{.*}} f2c 'const __mfp8' static +//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile __mfp8' //CHECK-NEXT: | |-AccessSpecDecl {{.*}} //CHECK-NEXT: | |-CXXConstructorDecl {{.*}} C1 'void (__mfp8)' implicit-inline -//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f1c' '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f3c' 'volatile __MFloat8_t' -//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t' +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8' +//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f1c' '__mfp8' +//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8' +//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8' +//CHECK-NEXT: | | |-CXXCtorInitializer {{.*}} 'f3c' 'volatile __mfp8' +//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '__mfp8' +//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8' //CHECK-NEXT: | | `-CompoundStmt {{.*}} //CHECK-NEXT: | |-CXXMethodDecl {{.*}} func1c '__mfp8 (__mfp8)' implicit-inline -//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t' +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} arg '__mfp8' //CHECK-NEXT: | | `-CompoundStmt {{.*}} //CHECK-NEXT: | | `-ReturnStmt {{.*}} -//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t' +//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '__mfp8' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8' //CHECK-NEXT: | `-CXXMethodDecl {{.*}} func2c '__mfp8 (__mfp8)' static implicit-inline -//CHECK-NEXT: | |-ParmVarDecl {{.*}} arg '__mfp8':'__MFloat8_t' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} arg '__mfp8' //CHECK-NEXT: | `-CompoundStmt {{.*}} //CHECK-NEXT: | `-ReturnStmt {{.*}} -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8':'__MFloat8_t' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__mfp8':'__MFloat8_t' lvalue ParmVar {{.*}} 'arg' '__mfp8':'__MFloat8_t' +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__mfp8' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__mfp8' lvalue ParmVar {{.*}} 'arg' '__mfp8' template struct S1 { C mem1; @@ -85,7 +84,7 @@ template <> struct S1<__mfp8> { __mfp8 mem2; }; -//CHECK: |-TemplateArgument type '__MFloat8_t' -//CHECK-NEXT: | `-BuiltinType {{.*}} '__MFloat8_t' +//CHECK: |-TemplateArgument type '__mfp8' +//CHECK-NEXT: | `-BuiltinType {{.*}} '__mfp8' //CHECK-NEXT: |-CXXRecordDecl {{.*}} implicit struct S1 -//CHECK-NEXT: `-FieldDecl {{.*}} mem2 '__mfp8':'__MFloat8_t' +//CHECK-NEXT: `-FieldDecl {{.*}} mem2 '__mfp8' diff --git a/clang/test/AST/ast-dump-comment.cpp b/clang/test/AST/ast-dump-comment.cpp index 8b058911d614d79bec1932b4574378ae359dc2e7..9798295b420f9a28ad6df22245070fa5c1dd62e5 100644 --- a/clang/test/AST/ast-dump-comment.cpp +++ b/clang/test/AST/ast-dump-comment.cpp @@ -73,6 +73,11 @@ int Test_InlineCommandCommentAnchor; // CHECK: VarDecl{{.*}}Test_InlineCommandComment // CHECK: InlineCommandComment{{.*}} Name="anchor" RenderAnchor Arg[0]="Aaa" +/// \relates Aaa +int Test_InlineCommandCommentRelates; +// CHECK: VarDecl{{.*}}Test_InlineCommandCommentRelates +// CHECK: InlineCommandComment{{.*}} Name="relates" RenderNormal Arg[0]="Aaa" + /// Aaa ///
int Test_HTMLTagComment; diff --git a/clang/test/AST/ast-print-openacc-combined-construct.cpp b/clang/test/AST/ast-print-openacc-combined-construct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6885806584f3d113f28511117e403a5587bcfb6e --- /dev/null +++ b/clang/test/AST/ast-print-openacc-combined-construct.cpp @@ -0,0 +1,125 @@ +// RUN: %clang_cc1 -fopenacc -Wno-openacc-deprecated-clause-alias -ast-print %s -o - | FileCheck %s + +void foo() { + int *iPtr; +// CHECK: #pragma acc parallel loop +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop + for(int i = 0;i<5;++i); +// CHECK: #pragma acc serial loop +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop + for(int i = 0;i<5;++i); +// CHECK: #pragma acc kernels loop +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop + for(int i = 0;i<5;++i); +// CHECK: #pragma acc parallel loop auto +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop auto + for(int i = 0;i<5;++i); +// CHECK: #pragma acc serial loop seq +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop seq + for(int i = 0;i<5;++i); +// CHECK: #pragma acc kernels loop independent +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop independent + for(int i = 0;i<5;++i); + + bool SomeB; + struct SomeStruct{} SomeStructImpl; + +//CHECK: #pragma acc parallel loop dtype(SomeB) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop dtype(SomeB) + for(int i = 0;i<5;++i); + +//CHECK: #pragma acc serial loop device_type(SomeStruct) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop device_type(SomeStruct) + for(int i = 0;i<5;++i); + +//CHECK: #pragma acc kernels loop device_type(int) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop device_type(int) + for(int i = 0;i<5;++i); + +//CHECK: #pragma acc parallel loop dtype(bool) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop dtype(bool) + for(int i = 0;i<5;++i); + +//CHECK: #pragma acc serial loop device_type(SomeStructImpl) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop device_type (SomeStructImpl) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc kernels loop dtype(AnotherIdent) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop dtype(AnotherIdent) + for(int i = 0;i<5;++i); + + int i; + float array[5]; + +// CHECK: #pragma acc parallel loop self(i == 3) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop self(i == 3) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc kernels loop if(i == array[1]) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop if(i == array[1]) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop default(none) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop default(none) + for(int i = 0;i<5;++i); +// CHECK: #pragma acc serial loop default(present) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop default(present) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc parallel loop private(i, array[1], array, array[1:2]) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc parallel loop private(i, array[1], array, array[1:2]) + for(int i = 0;i<5;++i); + +// CHECK: #pragma acc serial loop firstprivate(i, array[1], array, array[1:2]) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc serial loop firstprivate(i, array[1], array, array[1:2]) + for(int i = 0;i<5;++i); + + // CHECK: #pragma acc kernels loop async(*iPtr) +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop async(*iPtr) + for(int i = 0;i<5;++i); + + // CHECK: #pragma acc kernels loop async +// CHECK-NEXT: for (int i = 0; i < 5; ++i) +// CHECK-NEXT: ; +#pragma acc kernels loop async + for(int i = 0;i<5;++i); + +} diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da2eb0cf3d592ec0d4a803a0ab062406c1802fd1 --- /dev/null +++ b/clang/test/AST/attr-lifetime-capture-by.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -ast-dump | FileCheck %s + +// Verify that we print the [[clang::lifetime_capture_by(X)]] attribute. + +struct S { + void foo(int &a, int &b) [[clang::lifetime_capture_by(a, b, global)]]; +}; + +// CHECK: CXXMethodDecl {{.*}}clang::lifetime_capture_by(a, b, global) diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76f80a12c1703c10bf8d22f04b63deecc07f19fd --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/call-args-checked-const-member.cpp @@ -0,0 +1,63 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedCallArgsChecker -verify %s + +#include "mock-types.h" + +namespace call_args_const_checkedptr_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const CheckedPtr m_obj1; + CheckedPtr m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}} +} + +} // namespace call_args_const_checkedptr_member + +namespace call_args_const_checkedref_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const CheckedRef m_obj1; + CheckedRef m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}} +} + +} // namespace call_args_const_checkedref_member + +namespace call_args_const_unique_ptr { + +class Foo { +public: + Foo(); + void bar(); + +private: + const std::unique_ptr m_obj1; + std::unique_ptr m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is unchecked and unsafe}} +} + +} // namespace call_args_const_unique_ptr diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp index 34ff0c70e230ea4f3d5645e4e95b35358266e88c..072bceedcf9610ff240b1569105359785b9f923d 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args-checked-ptr.cpp @@ -365,3 +365,22 @@ namespace call_with_explicit_temporary_obj { CheckedPtr { provide() }->method(); } } + +namespace call_with_checked_ptr { + + class Foo : public CheckedObj { + public: + CheckedPtr obj1() { return m_obj; } + CheckedRef obj2() { return *m_obj; } + private: + CheckedObj* m_obj; + }; + + Foo* getFoo(); + + void bar() { + getFoo()->obj1()->method(); + getFoo()->obj2()->method(); + } + +} diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3296507a5c92d70db76a0154a800ec04eb3d30f --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +#include "mock-types.h" + +namespace std { +} + +namespace call_args_const_refptr_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const RefPtr m_obj1; + RefPtr m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} + +} // namespace call_args_const_refptr_member + +namespace call_args_const_ref_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const Ref m_obj1; + Ref m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} + +} // namespace call_args_const_ref_member + +namespace call_args_const_unique_ptr { + +class Foo { +public: + Foo(); + void bar(); + +private: + const std::unique_ptr m_obj1; + std::unique_ptr m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} + +} // namespace call_args_const_unique_ptr + +namespace call_args_const_unique_ref { + +class Foo { +public: + Foo(); + void bar(); + +private: + const UniqueRef m_obj1; + UniqueRef m_obj2; +}; + +void Foo::bar() { + m_obj1->method(); + m_obj2->method(); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} + +} // namespace call_args_const_unique_ref diff --git a/clang/test/Analysis/Checkers/WebKit/local-vars-checked-const-member.cpp b/clang/test/Analysis/Checkers/WebKit/local-vars-checked-const-member.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e52d1e735f6379eb088cf5a0fea7eb81954429b7 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/local-vars-checked-const-member.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncheckedLocalVarsChecker -verify %s + +#include "mock-types.h" +#include "mock-system-header.h" + +void someFunction(); + +namespace local_vars_const_checkedptr_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const CheckedPtr m_obj1; + CheckedPtr m_obj2; +}; + +void Foo::bar() { + auto* obj1 = m_obj1.get(); + obj1->method(); + auto* obj2 = m_obj2.get(); + // expected-warning@-1{{Local variable 'obj2' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} + obj2->method(); +} + +} // namespace local_vars_const_checkedptr_member + +namespace local_vars_const_checkedref_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const CheckedRef m_obj1; + CheckedRef m_obj2; +}; + +void Foo::bar() { + auto& obj1 = m_obj1.get(); + obj1.method(); + auto& obj2 = m_obj2.get(); + // expected-warning@-1{{Local variable 'obj2' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} + obj2.method(); +} + +} // namespace local_vars_const_ref_member + +namespace call_args_const_unique_ptr { + +class Foo { +public: + Foo(); + void bar(); + +private: + const std::unique_ptr m_obj1; + std::unique_ptr m_obj2; +}; + +void Foo::bar() { + auto* obj1 = m_obj1.get(); + obj1->method(); + auto* obj2 = m_obj2.get(); + // expected-warning@-1{{Local variable 'obj2' is unchecked and unsafe [alpha.webkit.UncheckedLocalVarsChecker]}} + obj2->method(); +} + +} // namespace call_args_const_unique_ptr diff --git a/clang/test/Analysis/Checkers/WebKit/local-vars-counted-const-member.cpp b/clang/test/Analysis/Checkers/WebKit/local-vars-counted-const-member.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03d16285f88b532a92a61d872b2b7c0479181e5e --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/local-vars-counted-const-member.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedLocalVarsChecker -verify %s + +#include "mock-types.h" +#include "mock-system-header.h" + +void someFunction(); + +namespace local_vars_const_refptr_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const RefPtr m_obj1; + RefPtr m_obj2; +}; + +void Foo::bar() { + auto* obj1 = m_obj1.get(); + obj1->method(); + auto* obj2 = m_obj2.get(); + // expected-warning@-1{{Local variable 'obj2' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}} + obj2->method(); +} + +} // namespace local_vars_const_refptr_member + +namespace local_vars_const_ref_member { + +class Foo { +public: + Foo(); + void bar(); + +private: + const Ref m_obj1; + Ref m_obj2; +}; + +void Foo::bar() { + auto& obj1 = m_obj1.get(); + obj1.method(); + auto& obj2 = m_obj2.get(); + // expected-warning@-1{{Local variable 'obj2' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}} + obj2.method(); +} + +} // namespace local_vars_const_ref_member + +namespace call_args_const_unique_ptr { + +class Foo { +public: + Foo(); + void bar(); + +private: + const std::unique_ptr m_obj1; + std::unique_ptr m_obj2; +}; + +void Foo::bar() { + auto* obj1 = m_obj1.get(); + obj1->method(); + auto* obj2 = m_obj2.get(); + // expected-warning@-1{{Local variable 'obj2' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}} + obj2->method(); +} + +} // namespace call_args_const_unique_ptr diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index 9c9326f0f11cfbc900eb6631e573e545e39fac3e..fb1ee51c7ec1dedaf1f673a391882b4d46cf70bf 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -66,11 +66,10 @@ template , typename RefDerefTra t = o.t; o.t = tmp; } - T &get() { return *PtrTraits::unwrap(t); } - T *ptr() { return PtrTraits::unwrap(t); } - T *operator->() { return PtrTraits::unwrap(t); } - operator const T &() const { return *PtrTraits::unwrap(t); } - operator T &() { return *PtrTraits::unwrap(t); } + T &get() const { return *PtrTraits::unwrap(t); } + T *ptr() const { return PtrTraits::unwrap(t); } + T *operator->() const { return PtrTraits::unwrap(t); } + operator T &() const { return *PtrTraits::unwrap(t); } T* leakRef() { return PtrTraits::exchange(t, nullptr); } }; @@ -102,9 +101,8 @@ template struct RefPtr { t = o.t; o.t = tmp; } - T *get() { return t; } - T *operator->() { return t; } - const T *operator->() const { return t; } + T *get() const { return t; } + T *operator->() const { return t; } T &operator*() { return *t; } RefPtr &operator=(T *t) { RefPtr o(t); @@ -135,7 +133,9 @@ struct RefCountable { void ref() {} void deref() {} void method(); + void constMethod() const; int trivial() { return 123; } + RefCountable* next(); }; template T *downcast(T *t) { return t; } @@ -149,9 +149,9 @@ public: CheckedRef(T &t) : t(&t) { t.incrementCheckedPtrCount(); } CheckedRef(const CheckedRef &o) : t(o.t) { if (t) t->incrementCheckedPtrCount(); } ~CheckedRef() { if (t) t->decrementCheckedPtrCount(); } - T &get() { return *t; } - T *ptr() { return t; } - T *operator->() { return t; } + T &get() const { return *t; } + T *ptr() const { return t; } + T *operator->() const { return t; } operator const T &() const { return *t; } operator T &() { return *t; } }; @@ -174,9 +174,8 @@ public: if (t) t->decrementCheckedPtrCount(); } - T *get() { return t; } - T *operator->() { return t; } - const T *operator->() const { return t; } + T *get() const { return t; } + T *operator->() const { return t; } T &operator*() { return *t; } CheckedPtr &operator=(T *) { return *this; } operator bool() const { return t; } @@ -200,4 +199,52 @@ public: int trivial() { return 0; } }; +template +class UniqueRef { +private: + T *t; + +public: + UniqueRef(T &t) : t(&t) { } + ~UniqueRef() { + if (t) + delete t; + } + template UniqueRef(UniqueRef&& u) + : t(u.t) + { + u.t = nullptr; + } + T &get() const { return *t; } + T *operator->() const { return t; } + UniqueRef &operator=(T &) { return *this; } +}; + +namespace std { + +template +class unique_ptr { +private: + T *t; + +public: + unique_ptr() : t(nullptr) { } + unique_ptr(T *t) : t(t) { } + ~unique_ptr() { + if (t) + delete t; + } + template unique_ptr(unique_ptr&& u) + : t(u.t) + { + u.t = nullptr; + } + T *get() const { return t; } + T *operator->() const { return t; } + T &operator*() { return *t; } + unique_ptr &operator=(T *) { return *this; } +}; + +}; + #endif diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index 27e0a74d583cd3bb8f3f30ca085e1c70f2eda129..9bfcdea04755d2446dd814edb896bd11bbafa5a4 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -1,39 +1,71 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker %s 2>&1 | FileCheck %s --strict-whitespace -#include "mock-types.h" +// RUN: %clang_analyze_cc1 -analyzer-checker=webkit.UncountedLambdaCapturesChecker -verify %s + +struct RefCountable { + void ref() {} + void deref() {} + void method(); + void constMethod() const; + int trivial() { return 123; } + RefCountable* next(); +}; + +RefCountable* make_obj(); + +void someFunction(); +template void call(Callback callback) { + someFunction(); + callback(); +} void raw_ptr() { - RefCountable* ref_countable = nullptr; - auto foo1 = [ref_countable](){}; - // CHECK: warning: Captured raw-pointer 'ref_countable' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] - // CHECK-NEXT:{{^ 6 | }} auto foo1 = [ref_countable](){}; - // CHECK-NEXT:{{^ | }} ^ - auto foo2 = [&ref_countable](){}; - // CHECK: warning: Captured raw-pointer 'ref_countable' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] - auto foo3 = [&](){ ref_countable = nullptr; }; - // CHECK: warning: Implicitly captured raw-pointer 'ref_countable' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] - // CHECK-NEXT:{{^ 12 | }} auto foo3 = [&](){ ref_countable = nullptr; }; - // CHECK-NEXT:{{^ | }} ^ - auto foo4 = [=](){ (void) ref_countable; }; - // CHECK: warning: Implicitly captured raw-pointer 'ref_countable' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] + RefCountable* ref_countable = make_obj(); + auto foo1 = [ref_countable](){ + // expected-warning@-1{{Captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + ref_countable->method(); + }; + auto foo2 = [&ref_countable](){ + // expected-warning@-1{{Captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + ref_countable->method(); + }; + auto foo3 = [&](){ + ref_countable->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + ref_countable = nullptr; + }; + + auto foo4 = [=](){ + ref_countable->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'ref_countable' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }; + + call(foo1); + call(foo2); + call(foo3); + call(foo4); // Confirm that the checker respects [[clang::suppress]]. RefCountable* suppressed_ref_countable = nullptr; [[clang::suppress]] auto foo5 = [suppressed_ref_countable](){}; - // CHECK-NOT: warning: Captured raw-pointer 'suppressed_ref_countable' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] + // no warning. + call(foo5); } void references() { RefCountable automatic; RefCountable& ref_countable_ref = automatic; + auto foo1 = [ref_countable_ref](){ ref_countable_ref.constMethod(); }; + // expected-warning@-1{{Captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + auto foo2 = [&ref_countable_ref](){ ref_countable_ref.method(); }; + // expected-warning@-1{{Captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + auto foo3 = [&](){ ref_countable_ref.method(); }; + // expected-warning@-1{{Implicitly captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + auto foo4 = [=](){ ref_countable_ref.constMethod(); }; + // expected-warning@-1{{Implicitly captured reference 'ref_countable_ref' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} - auto foo1 = [ref_countable_ref](){}; - // CHECK: warning: Captured reference 'ref_countable_ref' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] - auto foo2 = [&ref_countable_ref](){}; - // CHECK: warning: Captured reference 'ref_countable_ref' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] - auto foo3 = [&](){ (void) ref_countable_ref; }; - // CHECK: warning: Implicitly captured reference 'ref_countable_ref' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] - auto foo4 = [=](){ (void) ref_countable_ref; }; - // CHECK: warning: Implicitly captured reference 'ref_countable_ref' to uncounted type is unsafe [webkit.UncountedLambdaCapturesChecker] + call(foo1); + call(foo2); + call(foo3); + call(foo4); } void quiet() { @@ -45,5 +77,100 @@ void quiet() { auto foo3 = [&]() {}; auto foo4 = [=]() {}; + + call(foo3); + call(foo4); + RefCountable *ref_countable = nullptr; } + +template +void map(RefCountable* start, [[clang::noescape]] Callback&& callback) +{ + while (start) { + callback(*start); + start = start->next(); + } +} + +template +void doubleMap(RefCountable* start, [[clang::noescape]] Callback1&& callback1, Callback2&& callback2) +{ + while (start) { + callback1(*start); + callback2(*start); + start = start->next(); + } +} + +void noescape_lambda() { + RefCountable* someObj = make_obj(); + RefCountable* otherObj = make_obj(); + map(make_obj(), [&](RefCountable& obj) { + otherObj->method(); + }); + doubleMap(make_obj(), [&](RefCountable& obj) { + otherObj->method(); + }, [&](RefCountable& obj) { + otherObj->method(); + // expected-warning@-1{{Implicitly captured raw-pointer 'otherObj' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }); + ([&] { + someObj->method(); + })(); +} + +void lambda_capture_param(RefCountable* obj) { + auto someLambda = [&] { + obj->method(); + }; + someLambda(); + someLambda(); +} + +struct RefCountableWithLambdaCapturingThis { + void ref() const; + void deref() const; + void nonTrivial(); + + void method_captures_this_safe() { + auto lambda = [&]() { + nonTrivial(); + }; + lambda(); + } + + void method_captures_this_unsafe() { + auto lambda = [&]() { + nonTrivial(); + // expected-warning@-1{{Implicitly captured raw-pointer 'this' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + }; + call(lambda); + } +}; + +struct NonRefCountableWithLambdaCapturingThis { + void nonTrivial(); + + void method_captures_this_safe() { + auto lambda = [&]() { + nonTrivial(); + }; + lambda(); + } + + void method_captures_this_unsafe() { + auto lambda = [&]() { + nonTrivial(); + }; + call(lambda); + } +}; + +void trivial_lambda() { + RefCountable* ref_countable = make_obj(); + auto trivial_lambda = [&]() { + return ref_countable->trivial(); + }; + trivial_lambda(); +} diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp index e1dacdd9e25b6d304ad7b22cd1989247e2ef0e0e..d654d963a4faeffb2a524ae08f3398f20a71c13e 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -366,6 +366,8 @@ public: void trivial65() { __libcpp_verbose_abort("%s", "aborting"); } + RefPtr trivial66() { return children[0]; } + Ref trivial67() { return *children[0]; } static RefCounted& singleton() { static RefCounted s_RefCounted; @@ -550,6 +552,8 @@ public: getFieldTrivial().trivial63(); // no-warning getFieldTrivial().trivial64(); // no-warning getFieldTrivial().trivial65(); // no-warning + getFieldTrivial().trivial66()->trivial6(); // no-warning + getFieldTrivial().trivial67()->trivial6(); // no-warning RefCounted::singleton().trivial18(); // no-warning RefCounted::singleton().someFunction(); // no-warning diff --git a/clang/test/Analysis/ctor-trivial-copy.cpp b/clang/test/Analysis/ctor-trivial-copy.cpp index 5ed188aa8f1eae346587f5741de1680f2b5cb080..41d0d97161bba15e3d1bbfac3952d9bb99e7fa6b 100644 --- a/clang/test/Analysis/ctor-trivial-copy.cpp +++ b/clang/test/Analysis/ctor-trivial-copy.cpp @@ -1,8 +1,12 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=constructors -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config c++-inlining=constructors -verify %s \ +// RUN: 2>&1 | FileCheck %s -template -void clang_analyzer_dump(T&); +void clang_analyzer_printState(); +template void clang_analyzer_dump_lref(T&); +template void clang_analyzer_dump_val(T); +template T conjure(); +template void nop(const Ts &... args) {} struct aggr { int x; @@ -15,20 +19,104 @@ struct empty { void test_copy_return() { aggr s1 = {1, 2}; aggr const& cr1 = aggr(s1); - clang_analyzer_dump(cr1); // expected-warning-re {{&lifetime_extended_object{aggr, cr1, S{{[0-9]+}}} }} + clang_analyzer_dump_lref(cr1); // expected-warning-re {{&lifetime_extended_object{aggr, cr1, S{{[0-9]+}}} }} empty s2; empty const& cr2 = empty{s2}; - clang_analyzer_dump(cr2); // expected-warning-re {{&lifetime_extended_object{empty, cr2, S{{[0-9]+}}} }} + clang_analyzer_dump_lref(cr2); // expected-warning-re {{&lifetime_extended_object{empty, cr2, S{{[0-9]+}}} }} } void test_assign_return() { aggr s1 = {1, 2}; aggr d1; - clang_analyzer_dump(d1 = s1); // expected-warning {{&d1 }} + clang_analyzer_dump_lref(d1 = s1); // expected-warning {{&d1 }} empty s2; empty d2; - clang_analyzer_dump(d2 = s2); // expected-warning {{&d2 }} was Unknown + clang_analyzer_dump_lref(d2 = s2); // expected-warning {{&d2 }} was Unknown } + +namespace trivial_struct_copy { + +void _01_empty_structs() { + clang_analyzer_dump_val(conjure()); // expected-warning {{lazyCompoundVal}} + empty Empty = conjure(); + empty Empty2 = Empty; + empty Empty3 = Empty2; + // All of these should refer to the exact same LCV, because all of + // these trivial copies refer to the original conjured value. + // There were Unknown before: + clang_analyzer_dump_val(Empty); // expected-warning {{lazyCompoundVal}} + clang_analyzer_dump_val(Empty2); // expected-warning {{lazyCompoundVal}} + clang_analyzer_dump_val(Empty3); // expected-warning {{lazyCompoundVal}} + + // We should have the same Conjured symbol for "Empty", "Empty2" and "Empty3". + clang_analyzer_printState(); + // CHECK: "store": { "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "cluster": "GlobalInternalSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "GlobalSystemSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // 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: ]}, + + nop(Empty, Empty2, Empty3); +} + +void _02_structs_with_members() { + clang_analyzer_dump_val(conjure()); // expected-warning {{lazyCompoundVal}} + aggr Aggr = conjure(); + aggr Aggr2 = Aggr; + aggr Aggr3 = Aggr2; + // All of these should refer to the exact same LCV, because all of + // these trivial copies refer to the original conjured value. + clang_analyzer_dump_val(Aggr); // expected-warning {{lazyCompoundVal}} + clang_analyzer_dump_val(Aggr2); // expected-warning {{lazyCompoundVal}} + clang_analyzer_dump_val(Aggr3); // expected-warning {{lazyCompoundVal}} + + // We should have the same Conjured symbol for "Aggr", "Aggr2" and "Aggr3". + // We used to have Derived symbols for the individual fields that were + // copied as part of copying the whole struct. + clang_analyzer_printState(); + // CHECK: "store": { "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "cluster": "GlobalInternalSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "GlobalSystemSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "Aggr", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "[[AGGR_CONJ:conj_\$[0-9]+{int, LC[0-9]+, S[0-9]+, #[0-9]+}]]" } + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "Aggr2", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "[[AGGR_CONJ]]" } + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "Aggr3", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "[[AGGR_CONJ]]" } + // CHECK-NEXT: ]} + // CHECK-NEXT: ]}, + + nop(Aggr, Aggr2, Aggr3); +} + +// Tests that use `clang_analyzer_printState()` must share the analysis entry +// point, and have a strict ordering between. This is to meet the different +// `clang_analyzer_printState()` calls in a fixed relative ordering, thus +// FileCheck could check the stdouts. +void entrypoint() { + _01_empty_structs(); + _02_structs_with_members(); +} + +} // namespace trivial_struct_copy diff --git a/clang/test/Analysis/store-dump-orders.cpp b/clang/test/Analysis/store-dump-orders.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbe93f1c5183a9a907a199e5e202961cffc689ed --- /dev/null +++ b/clang/test/Analysis/store-dump-orders.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s 2>&1 | FileCheck %s +// expected-no-diagnostics + +void clang_analyzer_printState(); + +struct Member { + int large[10]; +}; +Member getMember(); + +struct Class { + Member m; + int first; + int second; + int third; +}; + + +void test_output(int n) { + Class objsecond; + objsecond.m.large[n] = 20; + + Class objfirst; + + objfirst.m = getMember(); + objfirst.second = 2; + objfirst.third = 3; + objfirst.first = 1; + + clang_analyzer_printState(); + // Default binding is before any direct bindings. + // Direct bindings are increasing by offset. + // Global memory space clusters come before any other clusters. + // Otherwise, Clusters are in alphabetical order. + + // CHECK: "store": { "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "cluster": "GlobalInternalSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "GlobalSystemSpaceRegion", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "objfirst", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "conj_$ + // CHECK-NEXT: { "kind": "Direct", "offset": 320, "value": "1 S32b" }, + // CHECK-NEXT: { "kind": "Direct", "offset": 352, "value": "2 S32b" }, + // CHECK-NEXT: { "kind": "Direct", "offset": 384, "value": "3 S32b" } + // CHECK-NEXT: ]}, + // CHECK-NEXT: { "cluster": "objsecond", "pointer": "0x{{[0-9a-f]+}}", "items": [ + // CHECK-NEXT: { "kind": "Default", "offset": 0, "value": "Unknown" }, + // CHECK-NEXT: { "kind": "Direct", "offset": null, "value": "20 S32b" } + // CHECK-NEXT: ]} + // CHECK-NEXT: ]}, + + (void)objfirst; + (void)objsecond; +} diff --git a/clang/test/Analysis/taint-generic.cpp b/clang/test/Analysis/taint-generic.cpp index 8092ac6f270b2a4574969b0215e3418866b60529..881c5baf889f6cdc6966e59d4f54f6944e4fbc20 100644 --- a/clang/test/Analysis/taint-generic.cpp +++ b/clang/test/Analysis/taint-generic.cpp @@ -1,10 +1,15 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=optin.taint,core,alpha.security.ArrayBoundV2 -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml -Wno-format-security -verify -std=c++11 %s +// RUN: %clang_analyze_cc1 -std=c++11 -Wno-format-security \ +// RUN: -analyzer-checker=core,optin.taint,alpha.security.ArrayBoundV2,debug.ExprInspection \ +// RUN: -analyzer-config optin.taint.TaintPropagation:Config=%S/Inputs/taint-generic-config.yaml \ +// RUN: -verify %s + +template void clang_analyzer_isTainted(T); #define BUFSIZE 10 int Buffer[BUFSIZE]; int scanf(const char*, ...); -int mySource1(); +template T mySource1(); int mySource3(); typedef struct _FILE FILE; @@ -136,3 +141,23 @@ void testReadingFromStdin(char **p) { fscanf(stdin, "%d", &n); Buffer[n] = 1; // expected-warning {{Potential out of bound access }} } + +namespace gh114270 { +class Empty {}; +class Aggr { +public: + int data; +}; + +void top() { + int Int = mySource1(); + clang_analyzer_isTainted(Int); // expected-warning {{YES}} + + Empty E = mySource1(); + clang_analyzer_isTainted(E); // expected-warning {{YES}} + + Aggr A = mySource1(); + clang_analyzer_isTainted(A); // expected-warning {{YES}} + clang_analyzer_isTainted(A.data); // expected-warning {{YES}} +} +} // namespace gh114270 diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp index 693ca29370cf3fa8cc9a10d29ac7be105124f229..da1f8201f55dccc914f0bcc4be713c90e48ea549 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp @@ -17,10 +17,10 @@ E get_e(); // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}} void f() { - get_s(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + get_s(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}} get_i(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} get_vi(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - get_e(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + get_e(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}} // Okay, warnings are not encouraged get_s_ref(); @@ -54,10 +54,10 @@ void f() { fp3 three; fp2_alias four; - one(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - two(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - three(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - four(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + one(); // expected-warning {{ignoring return value of type 'E' declared with 'nodiscard' attribute}} + two(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}} + three(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}} + four(); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard' attribute}} // These are all okay because of the explicit cast to void. (void)one(); @@ -84,8 +84,8 @@ LaterReason get_later_reason(); // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 extension}} void cxx20_use() { - get_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: reason}} - get_later_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: later reason}} + get_reason(); // expected-warning {{ignoring return value of type 'ReasonStruct' declared with 'nodiscard' attribute: reason}} + get_later_reason(); // expected-warning {{ignoring return value of type 'LaterReason' declared with 'nodiscard' attribute: later reason}} another_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: another reason}} conflicting_reason(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: special reason}} } @@ -115,20 +115,20 @@ void usage() { S('A'); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}} S(1); S(2.2); - Y(); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away either!}} + Y(); // expected-warning {{ignoring temporary of type 'Y' declared with 'nodiscard' attribute: Don't throw me away either!}} S s; - ConvertTo{}; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}} + ConvertTo{}; // expected-warning {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}} // AST is different in C++17 mode. Before, a move ctor for ConvertTo is there // as well, hence the constructor warning. - // since-cxx17-warning@+2 {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}} - // cxx11-warning@+1 {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away!}} + // since-cxx17-warning@+2 {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}} + // cxx11-warning@+1 {{ignoring temporary of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}} (ConvertTo) s; (int)s; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} (S)'c'; // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't let that S-Char go!}} - // since-cxx17-warning@+2 {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw me away!}} - // cxx11-warning@+1 {{ignoring temporary created by a constructor declared with 'nodiscard' attribute: Don't throw me away!}} + // since-cxx17-warning@+2 {{ignoring return value of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}} + // cxx11-warning@+1 {{ignoring temporary of type 'ConvertTo' declared with 'nodiscard' attribute: Don't throw me away!}} static_cast(s); static_cast(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} static_cast(s); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Don't throw away as a double}} diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp index a3543cff7d2c923ff37181b8a5760b56998d805d..b37517921b1ca4ce315c183355a45ebf058a4fda 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp @@ -8,7 +8,7 @@ namespace std_example { error_info enable_missile_safety_mode(); void launch_missiles(); void test_missiles() { - enable_missile_safety_mode(); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} + enable_missile_safety_mode(); // expected-warning {{ignoring return value of type 'error_info' declared with 'nodiscard'}} launch_missiles(); } diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp index 56920ea8e8cf20614da1cc9247da4b5fe613fab6..afcb133e48a1a86dbc8acfe9fa668e4c760965a1 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp @@ -49,3 +49,20 @@ void check() { test_type(g); test_type(h); // expected-note {{instantiation}} } + +namespace GH63009 { +struct S1 { + [[noreturn]] S1() { throw int {}; } +}; +struct S2 { + [[noreturn]] ~S2() { throw int {}; } +}; + +int test_no_return_constructor() { S1(); } // ok +int test_no_return_destructor() { S2(); } // ok + +int main() { + test_no_return_constructor(); + test_no_return_destructor(); +} +} diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp index ce90728861605fed8cf7b9f993c572979ef30a71..881742df7e8b2911195f21f6b8e6a0ae9342ef04 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p2-cxx0x.cpp @@ -1,7 +1,18 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fno-diagnostics-show-line-numbers -fcaret-diagnostics-max-lines=1 %s 2>&1 | FileCheck %s -strict-whitespace auto a() -> int; // ok const auto b() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'const auto'}} auto *c() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto *'}} auto (d() -> int); // expected-error {{trailing return type may not be nested within parentheses}} auto e() -> auto (*)() -> auto (*)() -> void; // ok: same as void (*(*e())())(); + +namespace GH78694 { + +template struct B { + // CHECK: error: function with trailing return type must specify return type 'auto', not 'void' + // CHECK-NEXT: {{^}} template B(U) -> B; + // CHECK-NEXT: {{^}} ~~~~~~~~^~~~~~{{$}} + template B(U) -> B; // expected-error {{function with trailing return type must specify return type 'auto', not 'void'}} +}; +} diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed-assembly.c b/clang/test/CodeGen/AArch64/ABI-align-packed-assembly.c similarity index 100% rename from clang/test/CodeGen/aarch64-ABI-align-packed-assembly.c rename to clang/test/CodeGen/AArch64/ABI-align-packed-assembly.c diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed.c b/clang/test/CodeGen/AArch64/ABI-align-packed.c similarity index 100% rename from clang/test/CodeGen/aarch64-ABI-align-packed.c rename to clang/test/CodeGen/AArch64/ABI-align-packed.c diff --git a/clang/test/CodeGen/aarch64-args-hfa.c b/clang/test/CodeGen/AArch64/args-hfa.c similarity index 100% rename from clang/test/CodeGen/aarch64-args-hfa.c rename to clang/test/CodeGen/AArch64/args-hfa.c diff --git a/clang/test/CodeGen/aarch64-args.cpp b/clang/test/CodeGen/AArch64/args.cpp similarity index 100% rename from clang/test/CodeGen/aarch64-args.cpp rename to clang/test/CodeGen/AArch64/args.cpp diff --git a/clang/test/CodeGen/aarch64-arguments-hfa-v3.c b/clang/test/CodeGen/AArch64/arguments-hfa-v3.c similarity index 100% rename from clang/test/CodeGen/aarch64-arguments-hfa-v3.c rename to clang/test/CodeGen/AArch64/arguments-hfa-v3.c diff --git a/clang/test/CodeGen/aarch64-attr-mode-complex.c b/clang/test/CodeGen/AArch64/attr-mode-complex.c similarity index 100% rename from clang/test/CodeGen/aarch64-attr-mode-complex.c rename to clang/test/CodeGen/AArch64/attr-mode-complex.c diff --git a/clang/test/CodeGen/aarch64-attr-mode-float.c b/clang/test/CodeGen/AArch64/attr-mode-float.c similarity index 100% rename from clang/test/CodeGen/aarch64-attr-mode-float.c rename to clang/test/CodeGen/AArch64/attr-mode-float.c diff --git a/clang/test/CodeGen/aarch64-bf16-dotprod-intrinsics.c b/clang/test/CodeGen/AArch64/bf16-dotprod-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-bf16-dotprod-intrinsics.c rename to clang/test/CodeGen/AArch64/bf16-dotprod-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c b/clang/test/CodeGen/AArch64/bf16-getset-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-bf16-getset-intrinsics.c rename to clang/test/CodeGen/AArch64/bf16-getset-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-bf16-lane-intrinsics.c b/clang/test/CodeGen/AArch64/bf16-lane-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-bf16-lane-intrinsics.c rename to clang/test/CodeGen/AArch64/bf16-lane-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-bf16-ldst-intrinsics.c b/clang/test/CodeGen/AArch64/bf16-ldst-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-bf16-ldst-intrinsics.c rename to clang/test/CodeGen/AArch64/bf16-ldst-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-bf16-reinterpret-intrinsics.c b/clang/test/CodeGen/AArch64/bf16-reinterpret-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-bf16-reinterpret-intrinsics.c rename to clang/test/CodeGen/AArch64/bf16-reinterpret-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-branch-protection-attr.c b/clang/test/CodeGen/AArch64/branch-protection-attr.c similarity index 100% rename from clang/test/CodeGen/aarch64-branch-protection-attr.c rename to clang/test/CodeGen/AArch64/branch-protection-attr.c diff --git a/clang/test/CodeGen/aarch64-byval-temp.c b/clang/test/CodeGen/AArch64/byval-temp.c similarity index 100% rename from clang/test/CodeGen/aarch64-byval-temp.c rename to clang/test/CodeGen/AArch64/byval-temp.c diff --git a/clang/test/CodeGen/aarch64-cpu-supports-target.c b/clang/test/CodeGen/AArch64/cpu-supports-target.c similarity index 100% rename from clang/test/CodeGen/aarch64-cpu-supports-target.c rename to clang/test/CodeGen/AArch64/cpu-supports-target.c diff --git a/clang/test/CodeGen/aarch64-cpu-supports.c b/clang/test/CodeGen/AArch64/cpu-supports.c similarity index 100% rename from clang/test/CodeGen/aarch64-cpu-supports.c rename to clang/test/CodeGen/AArch64/cpu-supports.c diff --git a/clang/test/CodeGen/aarch64-debug-sve-vector-types.c b/clang/test/CodeGen/AArch64/debug-sve-vector-types.c similarity index 100% rename from clang/test/CodeGen/aarch64-debug-sve-vector-types.c rename to clang/test/CodeGen/AArch64/debug-sve-vector-types.c diff --git a/clang/test/CodeGen/aarch64-debug-sve-vectorx2-types.c b/clang/test/CodeGen/AArch64/debug-sve-vectorx2-types.c similarity index 100% rename from clang/test/CodeGen/aarch64-debug-sve-vectorx2-types.c rename to clang/test/CodeGen/AArch64/debug-sve-vectorx2-types.c diff --git a/clang/test/CodeGen/aarch64-debug-sve-vectorx3-types.c b/clang/test/CodeGen/AArch64/debug-sve-vectorx3-types.c similarity index 100% rename from clang/test/CodeGen/aarch64-debug-sve-vectorx3-types.c rename to clang/test/CodeGen/AArch64/debug-sve-vectorx3-types.c diff --git a/clang/test/CodeGen/aarch64-debug-sve-vectorx4-types.c b/clang/test/CodeGen/AArch64/debug-sve-vectorx4-types.c similarity index 100% rename from clang/test/CodeGen/aarch64-debug-sve-vectorx4-types.c rename to clang/test/CodeGen/AArch64/debug-sve-vectorx4-types.c diff --git a/clang/test/CodeGen/AArch64/debug-types.c b/clang/test/CodeGen/AArch64/debug-types.c new file mode 100644 index 0000000000000000000000000000000000000000..19de2168caf7c71e5333a15d3718b890aeaa8ca0 --- /dev/null +++ b/clang/test/CodeGen/AArch64/debug-types.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp8 \ +// RUN: -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s + +// REQUIRES: aarch64-registered-target + +void test_locals(void) { + // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "__mfp8", {{.*}}, baseType: ![[ELTTYU8:[0-9]+]] + // CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "__mfp8", size: 8, encoding: DW_ATE_unsigned_char) + __mfp8 mfp8; +} diff --git a/clang/test/CodeGen/aarch64-elf-pauthabi.c b/clang/test/CodeGen/AArch64/elf-pauthabi.c similarity index 91% rename from clang/test/CodeGen/aarch64-elf-pauthabi.c rename to clang/test/CodeGen/AArch64/elf-pauthabi.c index 023fa8c18e1300b1511b1f3a3742e3bc40fe7240..b176f708db85b4566c7c36d9aeb464ffc5a3b48c 100644 --- a/clang/test/CodeGen/aarch64-elf-pauthabi.c +++ b/clang/test/CodeGen/AArch64/elf-pauthabi.c @@ -1,5 +1,3 @@ -//// TODO: also test with -fptrauth-elf-got when the driver flag is supported - // RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ // RUN: -fptrauth-intrinsics \ // RUN: -fptrauth-calls \ @@ -9,6 +7,7 @@ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-init-fini \ // RUN: -fptrauth-init-fini-address-discrimination \ +// RUN: -fptrauth-elf-got \ // RUN: -fptrauth-indirect-gotos \ // RUN: -fptrauth-type-info-vtable-pointer-discrimination \ // RUN: -fptrauth-function-pointer-type-discrimination %s | \ @@ -42,6 +41,9 @@ // RUN: -fptrauth-calls -fptrauth-init-fini -fptrauth-init-fini-address-discrimination %s | \ // RUN: FileCheck %s --check-prefix=INITFINIADDR +// RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ +// RUN: -fptrauth-elf-got %s | FileCheck %s --check-prefix=ELFGOT + // RUN: %clang_cc1 -triple aarch64-linux -emit-llvm -o - \ // RUN: -fptrauth-indirect-gotos %s | FileCheck %s --check-prefix=GOTOS @@ -54,7 +56,7 @@ // RUN: FileCheck %s --check-prefix=FPTRTYPE // ALL: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} -// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 3839} +// ALL: !{i32 1, !"aarch64-elf-pauthabi-version", i32 4095} // INTRIN: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} // INTRIN: !{i32 1, !"aarch64-elf-pauthabi-version", i32 1} @@ -80,6 +82,9 @@ // INITFINIADDR: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} // INITFINIADDR: !{i32 1, !"aarch64-elf-pauthabi-version", i32 194} +// ELFGOT: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} +// ELFGOT: !{i32 1, !"aarch64-elf-pauthabi-version", i32 256} + // GOTOS: !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458} // GOTOS: !{i32 1, !"aarch64-elf-pauthabi-version", i32 512} diff --git a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c b/clang/test/CodeGen/AArch64/fix-cortex-a53-835769.c similarity index 100% rename from clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c rename to clang/test/CodeGen/AArch64/fix-cortex-a53-835769.c diff --git a/clang/test/CodeGen/aarch64-fmv-dependencies.c b/clang/test/CodeGen/AArch64/fmv-dependencies.c similarity index 68% rename from clang/test/CodeGen/aarch64-fmv-dependencies.c rename to clang/test/CodeGen/AArch64/fmv-dependencies.c index 137f64d7c9c32c4e11bc8cee394e6e9e31bc7974..f74b7aa32c7dcafeed587ec84ffde765a4cad3a7 100644 --- a/clang/test/CodeGen/aarch64-fmv-dependencies.c +++ b/clang/test/CodeGen/AArch64/fmv-dependencies.c @@ -42,7 +42,7 @@ __attribute__((target_version("flagm"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Mflagm2() #[[flagm2:[0-9]+]] { __attribute__((target_version("flagm2"))) int fmv(void) { return 0; } -// CHECK: define dso_local i32 @fmv._Mfp() #[[ATTR0:[0-9]+]] { +// CHECK: define dso_local i32 @fmv._Mfp() #[[default:[0-9]+]] { __attribute__((target_version("fp"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Mfp16() #[[fp16:[0-9]+]] { @@ -78,7 +78,7 @@ __attribute__((target_version("predres"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Mrcpc() #[[rcpc:[0-9]+]] { __attribute__((target_version("rcpc"))) int fmv(void) { return 0; } -// CHECK: define dso_local i32 @fmv._Mrcpc2() #[[rcpc:[0-9]+]] { +// CHECK: define dso_local i32 @fmv._Mrcpc2() #[[rcpc2:[0-9]+]] { __attribute__((target_version("rcpc2"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Mrcpc3() #[[rcpc3:[0-9]+]] { @@ -99,7 +99,7 @@ __attribute__((target_version("sha2"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Msha3() #[[sha3:[0-9]+]] { __attribute__((target_version("sha3"))) int fmv(void) { return 0; } -// CHECK: define dso_local i32 @fmv._Msimd() #[[ATTR0:[0-9]+]] { +// CHECK: define dso_local i32 @fmv._Msimd() #[[default]] { __attribute__((target_version("simd"))) int fmv(void) { return 0; } // CHECK: define dso_local i32 @fmv._Msm4() #[[sm4:[0-9]+]] { @@ -150,47 +150,48 @@ int caller() { return fmv(); } -// CHECK: attributes #[[aes]] = { {{.*}} "target-features"="+aes,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[bf16]] = { {{.*}} "target-features"="+bf16,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[bti]] = { {{.*}} "target-features"="+bti,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[crc]] = { {{.*}} "target-features"="+crc,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[dit]] = { {{.*}} "target-features"="+dit,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[dotprod]] = { {{.*}} "target-features"="+dotprod,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[dpb]] = { {{.*}} "target-features"="+ccpp,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[dpb2]] = { {{.*}} "target-features"="+ccdp,+ccpp,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[f32mm]] = { {{.*}} "target-features"="+f32mm,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a" -// CHECK: attributes #[[f64mm]] = { {{.*}} "target-features"="+f64mm,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a" -// CHECK: attributes #[[fcma]] = { {{.*}} "target-features"="+complxnum,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[flagm]] = { {{.*}} "target-features"="+flagm,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[flagm2]] = { {{.*}} "target-features"="+altnzcv,+flagm,+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[ATTR0]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[fp16]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[fp16fml]] = { {{.*}} "target-features"="+fp-armv8,+fp16fml,+fullfp16,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[frintts]] = { {{.*}} "target-features"="+fp-armv8,+fptoint,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[i8mm]] = { {{.*}} "target-features"="+fp-armv8,+i8mm,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[jscvt]] = { {{.*}} "target-features"="+fp-armv8,+jsconv,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[ls64]] = { {{.*}} "target-features"="+fp-armv8,+ls64,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[lse]] = { {{.*}} "target-features"="+fp-armv8,+lse,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[memtag]] = { {{.*}} "target-features"="+fp-armv8,+mte,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[mops]] = { {{.*}} "target-features"="+fp-armv8,+mops,+neon,+outline-atomics,+v8a" -// CHECK: attributes #[[predres]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+predres,+v8a" -// CHECK: attributes #[[rcpc]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+rcpc,+v8a" -// CHECK: attributes #[[rcpc3]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+rcpc,+rcpc3,+v8a" -// CHECK: attributes #[[rdm]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+rdm,+v8a" -// CHECK: attributes #[[rng]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+rand,+v8a" -// CHECK: attributes #[[sb]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+sb,+v8a" -// CHECK: attributes #[[sha2]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+sha2,+v8a" -// CHECK: attributes #[[sha3]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+sha2,+sha3,+v8a" -// CHECK: attributes #[[sm4]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+sm4,+v8a" -// CHECK: attributes #[[sme]] = { {{.*}} "target-features"="+bf16,+fp-armv8,+neon,+outline-atomics,+sme,+v8a" -// CHECK: attributes #[[sme_f64f64]] = { {{.*}} "target-features"="+bf16,+fp-armv8,+neon,+outline-atomics,+sme,+sme-f64f64,+v8a" -// CHECK: attributes #[[sme_i16i64]] = { {{.*}} "target-features"="+bf16,+fp-armv8,+neon,+outline-atomics,+sme,+sme-i16i64,+v8a" -// CHECK: attributes #[[sme2]] = { {{.*}} "target-features"="+bf16,+fp-armv8,+neon,+outline-atomics,+sme,+sme2,+v8a" -// CHECK: attributes #[[ssbs]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+ssbs,+v8a" -// CHECK: attributes #[[sve]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a" -// CHECK: attributes #[[sve2]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+v8a" -// CHECK: attributes #[[sve2_aes]] = { {{.*}} "target-features"="+aes,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+sve2-aes,+v8a" -// CHECK: attributes #[[sve2_bitperm]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+sve2-bitperm,+v8a" -// CHECK: attributes #[[sve2_sha3]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+sve2-sha3,+v8a" -// CHECK: attributes #[[sve2_sm4]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+sve2-sm4,+v8a" -// CHECK: attributes #[[wfxt]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+v8a,+wfxt" +// CHECK: attributes #[[aes]] = { {{.*}} "target-features"="+aes,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[bf16]] = { {{.*}} "target-features"="+bf16,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[bti]] = { {{.*}} "target-features"="+bti,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[crc]] = { {{.*}} "target-features"="+crc,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[dit]] = { {{.*}} "target-features"="+dit,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[dotprod]] = { {{.*}} "target-features"="+dotprod,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[dpb]] = { {{.*}} "target-features"="+ccpp,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[dpb2]] = { {{.*}} "target-features"="+ccdp,+ccpp,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[f32mm]] = { {{.*}} "target-features"="+f32mm,+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a" +// CHECK: attributes #[[f64mm]] = { {{.*}} "target-features"="+f64mm,+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a" +// CHECK: attributes #[[fcma]] = { {{.*}} "target-features"="+complxnum,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[flagm]] = { {{.*}} "target-features"="+flagm,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[flagm2]] = { {{.*}} "target-features"="+altnzcv,+flagm,+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[default]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[fp16]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[fp16fml]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fp16fml,+fullfp16,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[frintts]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fptoint,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[i8mm]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+i8mm,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[jscvt]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+jsconv,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[ls64]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+ls64,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[lse]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+lse,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[memtag]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+mte,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[mops]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+mops,+neon,+outline-atomics,+v8a" +// CHECK: attributes #[[predres]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+predres,+v8a" +// CHECK: attributes #[[rcpc]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+rcpc,+v8a" +// CHECK: attributes #[[rcpc2]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+rcpc,+rcpc-immo,+v8a" +// CHECK: attributes #[[rcpc3]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+rcpc,+rcpc-immo,+rcpc3,+v8a" +// CHECK: attributes #[[rdm]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+rdm,+v8a" +// CHECK: attributes #[[rng]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+rand,+v8a" +// CHECK: attributes #[[sb]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+sb,+v8a" +// CHECK: attributes #[[sha2]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+sha2,+v8a" +// CHECK: attributes #[[sha3]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+sha2,+sha3,+v8a" +// CHECK: attributes #[[sm4]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+sm4,+v8a" +// CHECK: attributes #[[sme]] = { {{.*}} "target-features"="+bf16,+fmv,+fp-armv8,+neon,+outline-atomics,+sme,+v8a" +// CHECK: attributes #[[sme_f64f64]] = { {{.*}} "target-features"="+bf16,+fmv,+fp-armv8,+neon,+outline-atomics,+sme,+sme-f64f64,+v8a" +// CHECK: attributes #[[sme_i16i64]] = { {{.*}} "target-features"="+bf16,+fmv,+fp-armv8,+neon,+outline-atomics,+sme,+sme-i16i64,+v8a" +// CHECK: attributes #[[sme2]] = { {{.*}} "target-features"="+bf16,+fmv,+fp-armv8,+neon,+outline-atomics,+sme,+sme2,+v8a" +// CHECK: attributes #[[ssbs]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+ssbs,+v8a" +// CHECK: attributes #[[sve]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a" +// CHECK: attributes #[[sve2]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+v8a" +// CHECK: attributes #[[sve2_aes]] = { {{.*}} "target-features"="+aes,+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve-aes,+sve2,+sve2-aes,+v8a" +// CHECK: attributes #[[sve2_bitperm]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+sve2-bitperm,+v8a" +// CHECK: attributes #[[sve2_sha3]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sha2,+sha3,+sve,+sve2,+sve2-sha3,+v8a" +// CHECK: attributes #[[sve2_sm4]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sm4,+sve,+sve2,+sve2-sm4,+v8a" +// CHECK: attributes #[[wfxt]] = { {{.*}} "target-features"="+fmv,+fp-armv8,+neon,+outline-atomics,+v8a,+wfxt" diff --git a/clang/test/CodeGen/aarch64-fmv-resolver-emission.c b/clang/test/CodeGen/AArch64/fmv-resolver-emission.c similarity index 100% rename from clang/test/CodeGen/aarch64-fmv-resolver-emission.c rename to clang/test/CodeGen/AArch64/fmv-resolver-emission.c diff --git a/clang/test/CodeGen/AArch64/fmv-streaming.c b/clang/test/CodeGen/AArch64/fmv-streaming.c new file mode 100644 index 0000000000000000000000000000000000000000..dc0c35a9a30775efcb4bb0c70a71dcda442cf853 --- /dev/null +++ b/clang/test/CodeGen/AArch64/fmv-streaming.c @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -emit-llvm -o - %s | FileCheck %s + + +// CHECK-LABEL: define {{[^@]+}}@n_callee._Msve +// CHECK-SAME: () #[[locally_streaming_sve:[0-9]+]] { +// +// CHECK-LABEL: define {{[^@]+}}@n_callee._Msimd +// CHECK-SAME: () #[[locally_streaming_simd:[0-9]+]] { +// +__arm_locally_streaming __attribute__((target_clones("sve", "simd"))) void n_callee(void) {} +// CHECK-LABEL: define {{[^@]+}}@n_callee._Msme2 +// CHECK-SAME: () #[[sme2:[0-9]+]] { +// +__attribute__((target_version("sme2"))) void n_callee(void) {} +// CHECK-LABEL: define {{[^@]+}}@n_callee.default +// CHECK-SAME: () #[[default:[0-9]+]] { +// +__attribute__((target_version("default"))) void n_callee(void) {} + + +// CHECK-LABEL: define {{[^@]+}}@s_callee._Msve +// CHECK-SAME: () #[[sve_streaming:[0-9]+]] { +// +// CHECK-LABEL: define {{[^@]+}}@s_callee._Msimd +// CHECK-SAME: () #[[simd_streaming:[0-9]+]] { +// +__attribute__((target_clones("sve", "simd"))) void s_callee(void) __arm_streaming {} +// CHECK-LABEL: define {{[^@]+}}@s_callee._Msme2 +// CHECK-SAME: () #[[locally_streaming_sme2_streaming:[0-9]+]] { +// +__arm_locally_streaming __attribute__((target_version("sme2"))) void s_callee(void) __arm_streaming {} +// CHECK-LABEL: define {{[^@]+}}@s_callee.default +// CHECK-SAME: () #[[default_streaming:[0-9]+]] { +// +__attribute__((target_version("default"))) void s_callee(void) __arm_streaming {} + + +// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msve +// CHECK-SAME: () #[[sve_streaming_compatible:[0-9]+]] { +// +// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msimd +// CHECK-SAME: () #[[simd_streaming_compatible:[0-9]+]] { +// +__attribute__((target_clones("sve", "simd"))) void sc_callee(void) __arm_streaming_compatible {} +// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msme2 +// CHECK-SAME: () #[[locally_streaming_sme2_streaming_compatible:[0-9]+]] { +// +__arm_locally_streaming __attribute__((target_version("sme2"))) void sc_callee(void) __arm_streaming_compatible {} +// CHECK-LABEL: define {{[^@]+}}@sc_callee.default +// CHECK-SAME: () #[[default_streaming_compatible:[0-9]+]] { +// +__attribute__((target_version("default"))) void sc_callee(void) __arm_streaming_compatible {} + + +// CHECK-LABEL: define {{[^@]+}}@n_caller +// CHECK-SAME: () #[[caller:[0-9]+]] { +// CHECK: call void @n_callee() +// CHECK: call void @s_callee() #[[callsite_streaming:[0-9]+]] +// CHECK: call void @sc_callee() #[[callsite_streaming_compatible:[0-9]+]] +// +void n_caller(void) { + n_callee(); + s_callee(); + sc_callee(); +} + + +// CHECK-LABEL: define {{[^@]+}}@s_caller +// CHECK-SAME: () #[[caller_streaming:[0-9]+]] { +// CHECK: call void @n_callee() +// CHECK: call void @s_callee() #[[callsite_streaming]] +// CHECK: call void @sc_callee() #[[callsite_streaming_compatible]] +// +void s_caller(void) __arm_streaming { + n_callee(); + s_callee(); + sc_callee(); +} + + +// CHECK-LABEL: define {{[^@]+}}@sc_caller +// CHECK-SAME: () #[[caller_streaming_compatible:[0-9]+]] { +// CHECK: call void @n_callee() +// CHECK: call void @s_callee() #[[callsite_streaming]] +// CHECK: call void @sc_callee() #[[callsite_streaming_compatible]] +// +void sc_caller(void) __arm_streaming_compatible { + n_callee(); + s_callee(); + sc_callee(); +} + + +// CHECK: attributes #[[locally_streaming_sve]] = {{.*}} "aarch64_pstate_sm_body" +// CHECK: attributes #[[locally_streaming_simd]] = {{.*}} "aarch64_pstate_sm_body" +// CHECK: attributes #[[sme2]] = {{.*}} +// CHECK: attributes #[[default]] = {{.*}} +// CHECK: attributes #[[sve_streaming]] = {{.*}} "aarch64_pstate_sm_enabled" +// CHECK: attributes #[[simd_streaming]] = {{.*}} "aarch64_pstate_sm_enabled" +// CHECK: attributes #[[locally_streaming_sme2_streaming]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_enabled" +// CHECK: attributes #[[default_streaming]] = {{.*}} "aarch64_pstate_sm_enabled" +// CHECK: attributes #[[sve_streaming_compatible]] = {{.*}} "aarch64_pstate_sm_compatible" +// CHECK: attributes #[[simd_streaming_compatible]] = {{.*}} "aarch64_pstate_sm_compatible" +// CHECK: attributes #[[locally_streaming_sme2_streaming_compatible]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_compatible" +// CHECK: attributes #[[default_streaming_compatible]] = {{.*}} "aarch64_pstate_sm_compatible" +// CHECK: attributes #[[caller]] = {{.*}} +// CHECK: attributes #[[caller_streaming]] = {{.*}} "aarch64_pstate_sm_enabled" +// CHECK: attributes #[[caller_streaming_compatible]] = {{.*}} "aarch64_pstate_sm_compatible" +// CHECK: attributes #[[callsite_streaming]] = {{.*}} "aarch64_pstate_sm_enabled" +// CHECK: attributes #[[callsite_streaming_compatible]] = {{.*}} "aarch64_pstate_sm_compatible" diff --git a/clang/test/CodeGen/aarch64-fp8-intrinsics/acle_sme2_fp8_scale.c b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_scale.c similarity index 100% rename from clang/test/CodeGen/aarch64-fp8-intrinsics/acle_sme2_fp8_scale.c rename to clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sme2_fp8_scale.c diff --git a/clang/test/CodeGen/aarch64-fpm-helpers.c b/clang/test/CodeGen/AArch64/fpm-helpers.c similarity index 100% rename from clang/test/CodeGen/aarch64-fpm-helpers.c rename to clang/test/CodeGen/AArch64/fpm-helpers.c diff --git a/clang/test/CodeGen/aarch64-gcs.c b/clang/test/CodeGen/AArch64/gcs.c similarity index 100% rename from clang/test/CodeGen/aarch64-gcs.c rename to clang/test/CodeGen/AArch64/gcs.c diff --git a/clang/test/CodeGen/aarch64-inline-asm.c b/clang/test/CodeGen/AArch64/inline-asm.c similarity index 100% rename from clang/test/CodeGen/aarch64-inline-asm.c rename to clang/test/CodeGen/AArch64/inline-asm.c diff --git a/clang/test/CodeGen/aarch64-inlineasm-ios.c b/clang/test/CodeGen/AArch64/inlineasm-ios.c similarity index 100% rename from clang/test/CodeGen/aarch64-inlineasm-ios.c rename to clang/test/CodeGen/AArch64/inlineasm-ios.c diff --git a/clang/test/CodeGen/aarch64-ls64-inline-asm.c b/clang/test/CodeGen/AArch64/ls64-inline-asm.c similarity index 100% rename from clang/test/CodeGen/aarch64-ls64-inline-asm.c rename to clang/test/CodeGen/AArch64/ls64-inline-asm.c diff --git a/clang/test/CodeGen/aarch64-ls64.c b/clang/test/CodeGen/AArch64/ls64.c similarity index 100% rename from clang/test/CodeGen/aarch64-ls64.c rename to clang/test/CodeGen/AArch64/ls64.c diff --git a/clang/test/CodeGen/aarch64-matmul.cpp b/clang/test/CodeGen/AArch64/matmul.cpp similarity index 100% rename from clang/test/CodeGen/aarch64-matmul.cpp rename to clang/test/CodeGen/AArch64/matmul.cpp diff --git a/clang/test/CodeGen/aarch64-mixed-target-attributes.c b/clang/test/CodeGen/AArch64/mixed-target-attributes.c similarity index 99% rename from clang/test/CodeGen/aarch64-mixed-target-attributes.c rename to clang/test/CodeGen/AArch64/mixed-target-attributes.c index f9c1ae5b75a724284f68e4be9f2a71d34cb54ce3..bb6fb7eb8862a2d71ea18ab8e47b87206f0b6e85 100644 --- a/clang/test/CodeGen/aarch64-mixed-target-attributes.c +++ b/clang/test/CodeGen/AArch64/mixed-target-attributes.c @@ -198,7 +198,7 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@implicit_default.default -// CHECK-SAME: () #[[ATTR0]] { +// CHECK-SAME: () #[[ATTR6:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // diff --git a/clang/test/CodeGen/aarch64-mops.c b/clang/test/CodeGen/AArch64/mops.c similarity index 100% rename from clang/test/CodeGen/aarch64-mops.c rename to clang/test/CodeGen/AArch64/mops.c diff --git a/clang/test/CodeGen/aarch64-neon-2velem.c b/clang/test/CodeGen/AArch64/neon-2velem.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-2velem.c rename to clang/test/CodeGen/AArch64/neon-2velem.c diff --git a/clang/test/CodeGen/aarch64-neon-3v.c b/clang/test/CodeGen/AArch64/neon-3v.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-3v.c rename to clang/test/CodeGen/AArch64/neon-3v.c diff --git a/clang/test/CodeGen/aarch64-neon-across.c b/clang/test/CodeGen/AArch64/neon-across.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-across.c rename to clang/test/CodeGen/AArch64/neon-across.c diff --git a/clang/test/CodeGen/aarch64-neon-dot-product.c b/clang/test/CodeGen/AArch64/neon-dot-product.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-dot-product.c rename to clang/test/CodeGen/AArch64/neon-dot-product.c diff --git a/clang/test/CodeGen/aarch64-neon-extract.c b/clang/test/CodeGen/AArch64/neon-extract.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-extract.c rename to clang/test/CodeGen/AArch64/neon-extract.c diff --git a/clang/test/CodeGen/aarch64-neon-faminmax-intrinsics.c b/clang/test/CodeGen/AArch64/neon-faminmax-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-faminmax-intrinsics.c rename to clang/test/CodeGen/AArch64/neon-faminmax-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c b/clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-fcvt-intrinsics.c rename to clang/test/CodeGen/AArch64/neon-fcvt-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-neon-fma.c b/clang/test/CodeGen/AArch64/neon-fma.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-fma.c rename to clang/test/CodeGen/AArch64/neon-fma.c diff --git a/clang/test/CodeGen/aarch64-neon-fp16fml.c b/clang/test/CodeGen/AArch64/neon-fp16fml.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-fp16fml.c rename to clang/test/CodeGen/AArch64/neon-fp16fml.c diff --git a/clang/test/CodeGen/aarch64-neon-fp8-intrinsics/acle_neon_fscale.c b/clang/test/CodeGen/AArch64/neon-fp8-intrinsics/acle_neon_fscale.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-fp8-intrinsics/acle_neon_fscale.c rename to clang/test/CodeGen/AArch64/neon-fp8-intrinsics/acle_neon_fscale.c diff --git a/clang/test/CodeGen/aarch64-neon-intrinsics-constrained.c b/clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-intrinsics-constrained.c rename to clang/test/CodeGen/AArch64/neon-intrinsics-constrained.c diff --git a/clang/test/CodeGen/aarch64-neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-intrinsics.c rename to clang/test/CodeGen/AArch64/neon-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-neon-ldst-one-rcpc3.c b/clang/test/CodeGen/AArch64/neon-ldst-one-rcpc3.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-ldst-one-rcpc3.c rename to clang/test/CodeGen/AArch64/neon-ldst-one-rcpc3.c diff --git a/clang/test/CodeGen/aarch64-neon-ldst-one.c b/clang/test/CodeGen/AArch64/neon-ldst-one.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-ldst-one.c rename to clang/test/CodeGen/AArch64/neon-ldst-one.c diff --git a/clang/test/CodeGen/aarch64-neon-luti.c b/clang/test/CodeGen/AArch64/neon-luti.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-luti.c rename to clang/test/CodeGen/AArch64/neon-luti.c diff --git a/clang/test/CodeGen/aarch64-neon-misc-constrained.c b/clang/test/CodeGen/AArch64/neon-misc-constrained.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-misc-constrained.c rename to clang/test/CodeGen/AArch64/neon-misc-constrained.c diff --git a/clang/test/CodeGen/aarch64-neon-misc.c b/clang/test/CodeGen/AArch64/neon-misc.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-misc.c rename to clang/test/CodeGen/AArch64/neon-misc.c diff --git a/clang/test/CodeGen/aarch64-neon-perm.c b/clang/test/CodeGen/AArch64/neon-perm.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-perm.c rename to clang/test/CodeGen/AArch64/neon-perm.c diff --git a/clang/test/CodeGen/aarch64-neon-range-checks.c b/clang/test/CodeGen/AArch64/neon-range-checks.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-range-checks.c rename to clang/test/CodeGen/AArch64/neon-range-checks.c diff --git a/clang/test/CodeGen/aarch64-neon-scalar-copy.c b/clang/test/CodeGen/AArch64/neon-scalar-copy.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-scalar-copy.c rename to clang/test/CodeGen/AArch64/neon-scalar-copy.c diff --git a/clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem-constrained.c b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem-constrained.c rename to clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem-constrained.c diff --git a/clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c b/clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-scalar-x-indexed-elem.c rename to clang/test/CodeGen/AArch64/neon-scalar-x-indexed-elem.c diff --git a/clang/test/CodeGen/aarch64-neon-sha3.c b/clang/test/CodeGen/AArch64/neon-sha3.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-sha3.c rename to clang/test/CodeGen/AArch64/neon-sha3.c diff --git a/clang/test/CodeGen/aarch64-neon-shifts.c b/clang/test/CodeGen/AArch64/neon-shifts.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-shifts.c rename to clang/test/CodeGen/AArch64/neon-shifts.c diff --git a/clang/test/CodeGen/aarch64-neon-sm4-sm3.c b/clang/test/CodeGen/AArch64/neon-sm4-sm3.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-sm4-sm3.c rename to clang/test/CodeGen/AArch64/neon-sm4-sm3.c diff --git a/clang/test/CodeGen/aarch64-neon-tbl.c b/clang/test/CodeGen/AArch64/neon-tbl.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-tbl.c rename to clang/test/CodeGen/AArch64/neon-tbl.c diff --git a/clang/test/CodeGen/aarch64-neon-vcadd.c b/clang/test/CodeGen/AArch64/neon-vcadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vcadd.c rename to clang/test/CodeGen/AArch64/neon-vcadd.c diff --git a/clang/test/CodeGen/aarch64-neon-vcmla.c b/clang/test/CodeGen/AArch64/neon-vcmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vcmla.c rename to clang/test/CodeGen/AArch64/neon-vcmla.c diff --git a/clang/test/CodeGen/aarch64-neon-vcombine.c b/clang/test/CodeGen/AArch64/neon-vcombine.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vcombine.c rename to clang/test/CodeGen/AArch64/neon-vcombine.c diff --git a/clang/test/CodeGen/aarch64-neon-vget-hilo.c b/clang/test/CodeGen/AArch64/neon-vget-hilo.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vget-hilo.c rename to clang/test/CodeGen/AArch64/neon-vget-hilo.c diff --git a/clang/test/CodeGen/aarch64-neon-vget.c b/clang/test/CodeGen/AArch64/neon-vget.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vget.c rename to clang/test/CodeGen/AArch64/neon-vget.c diff --git a/clang/test/CodeGen/aarch64-neon-vsqadd-float-conversion.c b/clang/test/CodeGen/AArch64/neon-vsqadd-float-conversion.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vsqadd-float-conversion.c rename to clang/test/CodeGen/AArch64/neon-vsqadd-float-conversion.c diff --git a/clang/test/CodeGen/aarch64-neon-vuqadd-float-conversion-warning.c b/clang/test/CodeGen/AArch64/neon-vuqadd-float-conversion-warning.c similarity index 100% rename from clang/test/CodeGen/aarch64-neon-vuqadd-float-conversion-warning.c rename to clang/test/CodeGen/AArch64/neon-vuqadd-float-conversion-warning.c diff --git a/clang/test/CodeGen/aarch64-poly-add.c b/clang/test/CodeGen/AArch64/poly-add.c similarity index 100% rename from clang/test/CodeGen/aarch64-poly-add.c rename to clang/test/CodeGen/AArch64/poly-add.c diff --git a/clang/test/CodeGen/aarch64-poly128.c b/clang/test/CodeGen/AArch64/poly128.c similarity index 100% rename from clang/test/CodeGen/aarch64-poly128.c rename to clang/test/CodeGen/AArch64/poly128.c diff --git a/clang/test/CodeGen/aarch64-poly64.c b/clang/test/CodeGen/AArch64/poly64.c similarity index 100% rename from clang/test/CodeGen/aarch64-poly64.c rename to clang/test/CodeGen/AArch64/poly64.c diff --git a/clang/test/CodeGen/aarch64-pure-scalable-args-empty-union.c b/clang/test/CodeGen/AArch64/pure-scalable-args-empty-union.c similarity index 100% rename from clang/test/CodeGen/aarch64-pure-scalable-args-empty-union.c rename to clang/test/CodeGen/AArch64/pure-scalable-args-empty-union.c diff --git a/clang/test/CodeGen/aarch64-pure-scalable-args.c b/clang/test/CodeGen/AArch64/pure-scalable-args.c similarity index 98% rename from clang/test/CodeGen/aarch64-pure-scalable-args.c rename to clang/test/CodeGen/AArch64/pure-scalable-args.c index 53d5ce4e8c9d9b5ee0a92a07054c82565fcf906b..5c74447100aa8cd49b3d4d0d240bd415b978cabe 100644 --- a/clang/test/CodeGen/aarch64-pure-scalable-args.c +++ b/clang/test/CodeGen/AArch64/pure-scalable-args.c @@ -292,7 +292,7 @@ PST test_return(PST *p) { return *p; } // CHECK-AAPCS: define dso_local <{ , , , , , }> @test_return(ptr -// CHECK-DARWIN: define void @test_return(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.PST) align 16 %agg.result, ptr nocapture noundef readonly %p) +// CHECK-DARWIN: define void @test_return(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.PST) align 16 initializes((0, 96)) %agg.result, ptr nocapture noundef readonly %p) // Corner case of 1-element aggregate // p->x -> q0 @@ -308,8 +308,8 @@ SmallPST test_return_small_pst(SmallPST *p) { BigPST test_return_big_pst(BigPST *p) { return *p; } -// CHECK-AAPCS: define dso_local void @test_return_big_pst(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.BigPST) align 16 %agg.result, ptr nocapture noundef readonly %p) -// CHECK-DARWIN: define void @test_return_big_pst(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.BigPST) align 16 %agg.result, ptr nocapture noundef readonly %p) +// CHECK-AAPCS: define dso_local void @test_return_big_pst(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.BigPST) align 16 initializes((0, 176)) %agg.result, ptr nocapture noundef readonly %p) +// CHECK-DARWIN: define void @test_return_big_pst(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.BigPST) align 16 initializes((0, 176)) %agg.result, ptr nocapture noundef readonly %p) // Variadic arguments are unnamed, PST passed indirectly. // (Passing SVE types to a variadic function currently unsupported by diff --git a/clang/test/CodeGen/aarch64-sign-return-address.c b/clang/test/CodeGen/AArch64/sign-return-address.c similarity index 100% rename from clang/test/CodeGen/aarch64-sign-return-address.c rename to clang/test/CodeGen/AArch64/sign-return-address.c diff --git a/clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c b/clang/test/CodeGen/AArch64/sme-inline-streaming-attrs.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-inline-streaming-attrs.c rename to clang/test/CodeGen/AArch64/sme-inline-streaming-attrs.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp b/clang/test/CodeGen/AArch64/sme-intrinsics/aarch64-sme-attrs.cpp similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp rename to clang/test/CodeGen/AArch64/sme-intrinsics/aarch64-sme-attrs.cpp diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_add-i32.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_add-i32.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_add-i32.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_add-i32.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_add-i64.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_add-i64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_add-i64.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_add-i64.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_cnt.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_cnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_cnt.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_cnt.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1_vnum.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1_vnum.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ld1_vnum.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ld1_vnum.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ldr.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ldr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ldr.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_ldr.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mopa-za32.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mopa-za32.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mopa-za32.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mopa-za32.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mopa-za64.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mopa-za64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mopa-za64.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mopa-za64.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mops-za32.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mops-za32.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mops-za32.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mops-za32.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mops-za64.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mops-za64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_mops-za64.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_mops-za64.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_read.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_read.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_read.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_read.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1_vnum.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1_vnum.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_st1_vnum.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_st1_vnum.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_state_builtin.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_state_builtin.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_state_builtin.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_state_builtin.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_state_funs.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_state_funs.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_state_funs.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_state_funs.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_str.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_str.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_str.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_str.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_write.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_write.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_write.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_write.c diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c b/clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_zero.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c rename to clang/test/CodeGen/AArch64/sme-intrinsics/acle_sme_zero.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/aarch64-sme2-attrs.cpp b/clang/test/CodeGen/AArch64/sme2-intrinsics/aarch64-sme2-attrs.cpp similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/aarch64-sme2-attrs.cpp rename to clang/test/CodeGen/AArch64/sme2-intrinsics/aarch64-sme2-attrs.cpp diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_add.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_add.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add_sub_za16.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_add_sub_za16.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_add_sub_za16.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_add_sub_za16.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_bmop.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_bmop.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_bmop.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_bmop.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_clamp.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_clamp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_clamp.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_clamp.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_cvt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_cvt.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtl.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_cvtl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtl.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_cvtl.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtn.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_cvtn.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_cvtn.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_cvtn.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_faminmax.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_faminmax.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_faminmax.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_faminmax.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_fmlas16.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_fmlas16.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_fmlas16.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_fp_dots.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_fp_dots.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_fp_dots.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_fp_dots.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_frint.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_frint.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_frint.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_frint.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_int_dots.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_int_dots.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_int_dots.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_int_dots.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_ldr_str_zt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_ldr_str_zt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_ldr_str_zt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_ldr_str_zt.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti2_lane_zt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti2_lane_zt.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti2_lane_zt_x2.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti2_lane_zt_x4.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_lane_zt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_lane_zt.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_lane_zt_x2.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_lane_zt_x4.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_zt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_zt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_luti4_zt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_luti4_zt.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_max.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_max.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_max.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_maxnm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_maxnm.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_maxnm.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_min.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_min.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_min.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_minnm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_minnm.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_minnm.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mla.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mla.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mla.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlal.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mlal.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlal.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mlal.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlall.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mlall.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlall.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mlall.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mls.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mls.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mls.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mls.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlsl.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mlsl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mlsl.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mlsl.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mop.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mop.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mop.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mop.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mopa_nonwide.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_mopa_nonwide.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_mopa_nonwide.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_read.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_read.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_read.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_read.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_sqdmulh.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_sqdmulh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_sqdmulh.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_sqdmulh.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_sub.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_sub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_sub.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_sub.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx2.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_unpkx2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx2.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_unpkx2.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx4.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_unpkx4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_unpkx4.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_unpkx4.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vdot.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vdot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vdot.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vdot.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_add.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_add.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_add.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_add.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_qrshr.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_qrshr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_qrshr.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_qrshr.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_rshl.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_rshl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_rshl.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_rshl.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_selx2.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_selx2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_selx2.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_selx2.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_selx4.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_selx4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_selx4.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_selx4.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_uzpx2.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_uzpx2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_uzpx2.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_uzpx2.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_uzpx4.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_uzpx4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_uzpx4.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_uzpx4.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_zipx2.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_zipx2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_zipx2.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_zipx2.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_zipx4.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_zipx4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_vector_zipx4.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_vector_zipx4.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_write.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_write.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_write.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_write.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_write_lane_zt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_write_lane_zt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_write_lane_zt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_write_lane_zt.c diff --git a/clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_zero_zt.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_zero_zt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2-intrinsics/acle_sme2_zero_zt.c rename to clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_zero_zt.c diff --git a/clang/test/CodeGen/aarch64-sme2p1-intrinsics/acle_sme2p1_movaz.c b/clang/test/CodeGen/AArch64/sme2p1-intrinsics/acle_sme2p1_movaz.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2p1-intrinsics/acle_sme2p1_movaz.c rename to clang/test/CodeGen/AArch64/sme2p1-intrinsics/acle_sme2p1_movaz.c diff --git a/clang/test/CodeGen/aarch64-sme2p1-intrinsics/acle_sme2p1_zero.c b/clang/test/CodeGen/AArch64/sme2p1-intrinsics/acle_sme2p1_zero.c similarity index 100% rename from clang/test/CodeGen/aarch64-sme2p1-intrinsics/acle_sme2p1_zero.c rename to clang/test/CodeGen/AArch64/sme2p1-intrinsics/acle_sme2p1_zero.c diff --git a/clang/test/CodeGen/aarch64-soft-float-abi-errors.c b/clang/test/CodeGen/AArch64/soft-float-abi-errors.c similarity index 100% rename from clang/test/CodeGen/aarch64-soft-float-abi-errors.c rename to clang/test/CodeGen/AArch64/soft-float-abi-errors.c diff --git a/clang/test/CodeGen/aarch64-soft-float-abi.c b/clang/test/CodeGen/AArch64/soft-float-abi.c similarity index 100% rename from clang/test/CodeGen/aarch64-soft-float-abi.c rename to clang/test/CodeGen/AArch64/soft-float-abi.c diff --git a/clang/test/CodeGen/aarch64-strictfp-builtins.c b/clang/test/CodeGen/AArch64/strictfp-builtins.c similarity index 100% rename from clang/test/CodeGen/aarch64-strictfp-builtins.c rename to clang/test/CodeGen/AArch64/strictfp-builtins.c diff --git a/clang/test/CodeGen/aarch64-subarch-compatbility.c b/clang/test/CodeGen/AArch64/subarch-compatbility.c similarity index 100% rename from clang/test/CodeGen/aarch64-subarch-compatbility.c rename to clang/test/CodeGen/AArch64/subarch-compatbility.c diff --git a/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c b/clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c similarity index 98% rename from clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c rename to clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c index 55e1ed393d848bbe3769a0ede8307b8ad307aeef..54e90223a31de0e4e4c11628c742924dd0bdff3c 100644 --- a/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c +++ b/clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.c @@ -59,7 +59,7 @@ typedef int8_t vec_int8 __attribute__((vector_size(N / 8))); // CHECK128-NEXT: ret <16 x i8> [[CASTFIXEDSVE]] // CHECK-LABEL: define{{.*}} void @f2( -// CHECK-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret(<[[#div(VBITS,8)]] x i8>) align 16 %agg.result, ptr nocapture noundef readonly %0) +// CHECK-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret(<[[#div(VBITS,8)]] x i8>) align 16 initializes((0, [[#div(VBITS,8)]])) %agg.result, ptr nocapture noundef readonly %0) // CHECK-NEXT: entry: // CHECK-NEXT: [[X:%.*]] = load <[[#div(VBITS,8)]] x i8>, ptr [[TMP0:%.*]], align 16, [[TBAA6:!tbaa !.*]] // CHECK-NEXT: [[TMP1:%.*]] = tail call @llvm.aarch64.sve.ptrue.nxv16i1(i32 31) diff --git a/clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.cpp b/clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.cpp similarity index 100% rename from clang/test/CodeGen/aarch64-sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.cpp rename to clang/test/CodeGen/AArch64/sve-acle-__ARM_FEATURE_SVE_VECTOR_OPERATORS.cpp diff --git a/clang/test/CodeGen/aarch64-sve-inline-asm-crash.c b/clang/test/CodeGen/AArch64/sve-inline-asm-crash.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-inline-asm-crash.c rename to clang/test/CodeGen/AArch64/sve-inline-asm-crash.c diff --git a/clang/test/CodeGen/aarch64-sve-inline-asm-datatypes.c b/clang/test/CodeGen/AArch64/sve-inline-asm-datatypes.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-inline-asm-datatypes.c rename to clang/test/CodeGen/AArch64/sve-inline-asm-datatypes.c diff --git a/clang/test/CodeGen/aarch64-sve-inline-asm-negative-test.c b/clang/test/CodeGen/AArch64/sve-inline-asm-negative-test.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-inline-asm-negative-test.c rename to clang/test/CodeGen/AArch64/sve-inline-asm-negative-test.c diff --git a/clang/test/CodeGen/aarch64-sve-inline-asm.c b/clang/test/CodeGen/AArch64/sve-inline-asm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-inline-asm.c rename to clang/test/CodeGen/AArch64/sve-inline-asm.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/README b/clang/test/CodeGen/AArch64/sve-intrinsics/README similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/README rename to clang/test/CodeGen/AArch64/sve-intrinsics/README diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_abd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_abd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_abd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_abd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_abs.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_abs.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_abs.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_abs.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_acge.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_acge.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_acge.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_acge.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_acgt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_acgt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_acgt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_acgt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_acle.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_acle.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_acle.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_acle.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_aclt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_aclt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_aclt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_aclt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_add.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_add.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_add.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_add.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adda.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adda.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adda.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adda.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_addv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_addv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_addv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_addv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_adrw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_adrw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_and.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_and.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_and.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_and.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_andv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_andv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_andv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_andv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_asr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_asr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_asrd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_asrd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfdot.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfdot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfdot.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfdot.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfmlalb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfmlalb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfmlalb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfmlalb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfmlalt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfmlalt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfmlalt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfmlalt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfmmla.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfmmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bfmmla.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bfmmla.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bic.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bic.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_bic.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_bic.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brka.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brka.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brka.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brka.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkn.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkn.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkn.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkn.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkpa.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkpa.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkpa.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkpa.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkpb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkpb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_brkpb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_brkpb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cadd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cadd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cadd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clasta-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clasta-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clasta-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clasta-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clasta.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clasta.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clasta.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clasta.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clastb-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clastb-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clastb-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clastb-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clastb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clastb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clastb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clastb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cls.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cls.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cls.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cls.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clz.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clz.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_clz.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_clz.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmla.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpeq.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpeq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpeq.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpeq.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpge.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpge.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpge.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpge.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpgt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpgt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpgt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpgt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmple.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmple.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmple.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmple.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmplt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmplt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmplt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmplt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpne.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpne.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpne.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpne.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpuo.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpuo.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmpuo.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cmpuo.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnot.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnot.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnot.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnt-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnt-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnt-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnt-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnth.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnth.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cnth.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cnth.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntp.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntp.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntp.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cntw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cntw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_compact.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_compact.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_compact.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_compact.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create3-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create3-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create3-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create3-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create3.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create3.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create3.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create4-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create4-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create4-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create4-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create4.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_create4.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_create4.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cvt-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cvt-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cvt-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cvt-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cvt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cvt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cvt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cvt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cvtnt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cvtnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cvtnt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_cvtnt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_div.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_div.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_div.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_div.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_divr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_divr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_divr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_divr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dot.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dup-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dup-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dup-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dup-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dup.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dup.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dup.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dup.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dupq-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dupq-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dupq-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dupq-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dupq.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dupq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dupq.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dupq.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dupq_const.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dupq_const.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dupq_const.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_dupq_const.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_eor.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_eor.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_eor.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_eor.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_eorv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_eorv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_eorv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_eorv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_expa.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_expa.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_expa.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_expa.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ext-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ext-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ext.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ext.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_extb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_extb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_extb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_extb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_exth.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_exth.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_exth.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_exth.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_extw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_extw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_extw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_extw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get3-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get3-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get3-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get3-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get3.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get3.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get3.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get4-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get4-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get4-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get4-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get4.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_get4.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_get4.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_index.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_index.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_index.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_index.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_insr-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_insr-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_insr-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_insr-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_insr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_insr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_insr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_insr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lasta-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lasta-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lasta-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lasta-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lasta.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lasta.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lasta.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lasta.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lastb-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lastb-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lastb-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lastb-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lastb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lastb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lastb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lastb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1ro-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1ro-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1ro-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1ro-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1ro.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1ro.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1ro.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1ro.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1rq-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1rq-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1rq-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1rq-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1rq.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1rq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1rq.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1rq.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1sb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1sb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1sb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1sb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1sh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1sh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1sh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1sh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1sw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1sw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1sw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1sw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1ub.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1ub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1ub.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1ub.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1uh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1uh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1uh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1uh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1uw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1uw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1uw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld1uw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld3-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld3-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld3-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld3-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld3.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld3.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld3.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld4-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld4-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld4-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld4-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld4.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld4.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ld4.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1sb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1sb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1sb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1sb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1sh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1sh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1sh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1sh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1sw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1sw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1sw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1sw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1ub.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1ub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1ub.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1ub.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1uh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1uh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1uh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1uh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1uw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1uw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldff1uw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldff1uw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1sb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1sb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1sb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1sb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1sh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1sh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1sh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1sh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1sw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1sw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1sw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1sw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1ub.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1ub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1ub.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1ub.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1uh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1uh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1uh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1uh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1uw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1uw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnf1uw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnf1uw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnt1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnt1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnt1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnt1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnt1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnt1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ldnt1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ldnt1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_len-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_len-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_len-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_len-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_len.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_len.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_len.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_len.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lsl.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lsl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lsl.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lsl.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lsr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lsr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_lsr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_lsr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mad.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mad.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mad.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mad.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_matmul_fp32.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_matmul_fp32.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_matmul_fp32.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_matmul_fp32.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_matmul_fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_matmul_fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_matmul_fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_matmul_fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_max.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_max.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_max.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_max.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_maxnm.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_maxnm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_maxnm.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_maxnm.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_maxnmv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_maxnmv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_maxnmv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_maxnmv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_maxv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_maxv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_maxv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_maxv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_min.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_min.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_min.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_min.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_minnm.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_minnm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_minnm.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_minnm.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_minnmv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_minnmv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_minnmv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_minnmv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_minv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_minv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_minv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_minv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mla.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mls.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mls.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mls.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mls.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mmla.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mmla.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mmla.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mov.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mov.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mov.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mov.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_msb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_msb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_msb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_msb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mul.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mul.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mul.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mul.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mulh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mulh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mulh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mulh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mulx.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mulx.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mulx.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_mulx.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nand.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nand.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nand.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nand.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_neg.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_neg.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_neg.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_neg.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmad.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmad.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmad.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmad.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmla.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmla.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmla.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmls.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmls.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmls.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmls.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmsb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmsb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nmsb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nmsb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nor.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nor.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_nor.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_nor.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_not.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_not.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_not.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_not.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_orn.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_orn.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_orn.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_orn.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_orr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_orr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_orr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_orr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_orv.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_orv.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_orv.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_orv.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pfalse.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_pfalse.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pfalse.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_pfalse.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pfirst.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_pfirst.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pfirst.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_pfirst.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pnext.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_pnext.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_pnext.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_pnext.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_prfw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ptest.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ptest.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ptest.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ptest.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ptrue.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ptrue.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ptrue.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_ptrue.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qadd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qadd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qadd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdech.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdech.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdech.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdech.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecp.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecp.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecp.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdecw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qdecw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincd.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincd.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincd.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qinch.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qinch.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qinch.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qinch.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincp.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincp.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincp.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qincw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qincw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qsub.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qsub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qsub.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_qsub.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rbit.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rbit.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rbit.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rbit.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rdffr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rdffr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rdffr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rdffr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_recpe.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_recpe.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_recpe.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_recpe.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_recps.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_recps.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_recps.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_recps.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_recpx.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_recpx.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_recpx.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_recpx.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_reinterpret.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rev-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rev-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rev-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rev-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rev.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rev.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rev.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rev.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_revb.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_revb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_revb.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_revb.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_revh.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_revh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_revh.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_revh.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_revw.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_revw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_revw.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_revw.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rinta.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rinta.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rinta.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rinta.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rinti.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rinti.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rinti.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rinti.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintm.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintm.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintm.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintn.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintn.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintn.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintn.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintp.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintp.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintp.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintx.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintx.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintx.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintx.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintz.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintz.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rintz.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rintz.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rsqrte.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rsqrte.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rsqrte.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rsqrte.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rsqrts.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rsqrts.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_rsqrts.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_rsqrts.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_scale.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_scale.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_scale.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_scale.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sel-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sel-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sel-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sel-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sel.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sel.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sel.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sel.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set3-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set3-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set3-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set3-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set3.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set3.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set3.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set4-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set4-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set4-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set4-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set4.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_set4.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_set4.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_setffr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_setffr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_setffr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_setffr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_splice-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_splice-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_splice-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_splice-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_splice.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_splice.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_splice.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_splice.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sqrt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sqrt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sqrt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sqrt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1b.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1b.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1b.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1b.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1h.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1h.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1h.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1h.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1w.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1w.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st1w.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st1w.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st3-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st3-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st3-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st3-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st3.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st3.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st3.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st4-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st4-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st4-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st4-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st4.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_st4.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_st4.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_stnt1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_stnt1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_stnt1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_stnt1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_stnt1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_stnt1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_stnt1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_stnt1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sub.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sub.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sub.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_subr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_subr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_subr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_subr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sudot.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sudot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_sudot.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_sudot.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tbl-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tbl-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tbl-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tbl-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tbl.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tbl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tbl.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tbl.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tmad.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tmad.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1-fp64-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1-fp64-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1-fp64-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1-fp64-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1-fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1-fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1-fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1-fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2-fp64-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2-fp64-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2-fp64-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2-fp64-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2-fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2-fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2-fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2-fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_trn2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_trn2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tsmul.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tsmul.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tsmul.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tsmul.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tssel.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tssel.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tssel.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_tssel.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef3-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef3-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef3-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef3-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef3.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef3.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef3.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef4-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef4-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef4-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef4-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef4.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef4.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef4.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_undef4.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_unpkhi.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_unpkhi.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_unpkhi.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_unpkhi.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_unpklo.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_unpklo.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_unpklo.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_unpklo.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_usdot.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_usdot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_usdot.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_usdot.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1-fp64-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1-fp64-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1-fp64-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1-fp64-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1-fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1-fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1-fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1-fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2-fp64-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2-fp64-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2-fp64-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2-fp64-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2-fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2-fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2-fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2-fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_uzp2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_uzp2.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_whilele.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_whilele.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_whilele.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_whilele.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_whilelt.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_whilelt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_whilelt.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_whilelt.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_wrffr.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_wrffr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_wrffr.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_wrffr.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1-fp64-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1-fp64-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1-fp64-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1-fp64-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1-fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1-fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1-fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1-fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip1.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip1.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2-fp64-bfloat.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2-fp64-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2-fp64-bfloat.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2-fp64-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2-fp64.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2-fp64.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2-fp64.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2-fp64.c diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2.c b/clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_zip2.c rename to clang/test/CodeGen/AArch64/sve-intrinsics/acle_sve_zip2.c diff --git a/clang/test/CodeGen/aarch64-sve-vector-arith-ops.c b/clang/test/CodeGen/AArch64/sve-vector-arith-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vector-arith-ops.c rename to clang/test/CodeGen/AArch64/sve-vector-arith-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vector-bits-codegen.c b/clang/test/CodeGen/AArch64/sve-vector-bits-codegen.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vector-bits-codegen.c rename to clang/test/CodeGen/AArch64/sve-vector-bits-codegen.c diff --git a/clang/test/CodeGen/aarch64-sve-vector-bitwise-ops.c b/clang/test/CodeGen/AArch64/sve-vector-bitwise-ops.c similarity index 76% rename from clang/test/CodeGen/aarch64-sve-vector-bitwise-ops.c rename to clang/test/CodeGen/AArch64/sve-vector-bitwise-ops.c index 5b97ce44e87365cf57d0900f3605b8d633308e23..291d72de42c06f51b3d3e08beb81e308e7e1d075 100644 --- a/clang/test/CodeGen/aarch64-sve-vector-bitwise-ops.c +++ b/clang/test/CodeGen/AArch64/sve-vector-bitwise-ops.c @@ -260,8 +260,8 @@ svuint64_t xor_u64(svuint64_t a, svuint64_t b) { // CHECK-LABEL: @neg_bool( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i1 true) +// CHECK-NEXT: ret [[NOT]] // svbool_t neg_bool(svbool_t a) { return ~a; @@ -269,8 +269,8 @@ svbool_t neg_bool(svbool_t a) { // CHECK-LABEL: @neg_i8( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i8 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i8 -1) +// CHECK-NEXT: ret [[NOT]] // svint8_t neg_i8(svint8_t a) { return ~a; @@ -278,8 +278,8 @@ svint8_t neg_i8(svint8_t a) { // CHECK-LABEL: @neg_i16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i16 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i16 -1) +// CHECK-NEXT: ret [[NOT]] // svint16_t neg_i16(svint16_t a) { return ~a; @@ -287,8 +287,8 @@ svint16_t neg_i16(svint16_t a) { // CHECK-LABEL: @neg_i32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i32 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i32 -1) +// CHECK-NEXT: ret [[NOT]] // svint32_t neg_i32(svint32_t a) { return ~a; @@ -296,8 +296,8 @@ svint32_t neg_i32(svint32_t a) { // CHECK-LABEL: @neg_i64( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i64 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i64 -1) +// CHECK-NEXT: ret [[NOT]] // svint64_t neg_i64(svint64_t a) { return ~a; @@ -305,8 +305,8 @@ svint64_t neg_i64(svint64_t a) { // CHECK-LABEL: @neg_u8( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i8 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i8 -1) +// CHECK-NEXT: ret [[NOT]] // svuint8_t neg_u8(svuint8_t a) { return ~a; @@ -314,8 +314,8 @@ svuint8_t neg_u8(svuint8_t a) { // CHECK-LABEL: @neg_u16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i16 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i16 -1) +// CHECK-NEXT: ret [[NOT]] // svuint16_t neg_u16(svuint16_t a) { return ~a; @@ -323,8 +323,8 @@ svuint16_t neg_u16(svuint16_t a) { // CHECK-LABEL: @neg_u32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i32 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i32 -1) +// CHECK-NEXT: ret [[NOT]] // svuint32_t neg_u32(svuint32_t a) { return ~a; @@ -332,8 +332,8 @@ svuint32_t neg_u32(svuint32_t a) { // CHECK-LABEL: @neg_u64( // CHECK-NEXT: entry: -// CHECK-NEXT: [[NEG:%.*]] = xor [[A:%.*]], shufflevector ( insertelement ( poison, i64 -1, i64 0), poison, zeroinitializer) -// CHECK-NEXT: ret [[NEG]] +// CHECK-NEXT: [[NOT:%.*]] = xor [[A:%.*]], splat (i64 -1) +// CHECK-NEXT: ret [[NOT]] // svuint64_t neg_u64(svuint64_t a) { return ~a; diff --git a/clang/test/CodeGen/aarch64-sve-vector-compare-ops.c b/clang/test/CodeGen/AArch64/sve-vector-compare-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vector-compare-ops.c rename to clang/test/CodeGen/AArch64/sve-vector-compare-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vector-shift-ops.c b/clang/test/CodeGen/AArch64/sve-vector-shift-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vector-shift-ops.c rename to clang/test/CodeGen/AArch64/sve-vector-shift-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c b/clang/test/CodeGen/AArch64/sve-vector-subscript-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vector-subscript-ops.c rename to clang/test/CodeGen/AArch64/sve-vector-subscript-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vls-arith-ops.c b/clang/test/CodeGen/AArch64/sve-vls-arith-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vls-arith-ops.c rename to clang/test/CodeGen/AArch64/sve-vls-arith-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c b/clang/test/CodeGen/AArch64/sve-vls-bitwise-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vls-bitwise-ops.c rename to clang/test/CodeGen/AArch64/sve-vls-bitwise-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vls-compare-ops.c b/clang/test/CodeGen/AArch64/sve-vls-compare-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vls-compare-ops.c rename to clang/test/CodeGen/AArch64/sve-vls-compare-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vls-shift-ops.c b/clang/test/CodeGen/AArch64/sve-vls-shift-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vls-shift-ops.c rename to clang/test/CodeGen/AArch64/sve-vls-shift-ops.c diff --git a/clang/test/CodeGen/aarch64-sve-vls-subscript-ops.c b/clang/test/CodeGen/AArch64/sve-vls-subscript-ops.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve-vls-subscript-ops.c rename to clang/test/CodeGen/AArch64/sve-vls-subscript-ops.c diff --git a/clang/test/CodeGen/aarch64-sve.c b/clang/test/CodeGen/AArch64/sve.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve.c rename to clang/test/CodeGen/AArch64/sve.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aba.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aba.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aba.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aba.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abalb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abalb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abalb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abalb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abalt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abalt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abalt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abalt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abdlb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abdlb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abdlb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abdlb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abdlt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abdlt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_abdlt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_abdlt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_adalp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_adalp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_adalp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_adalp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_adclb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_adclb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_adclb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_adclb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_adclt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_adclt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_adclt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_adclt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addhnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addhnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addhnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addhnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addhnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addhnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addhnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addhnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addlb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addlb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addlb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addlb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addlbt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addlbt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addlbt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addlbt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addlt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addlt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addlt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addlt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addwb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addwb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addwb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addwb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addwt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addwt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_addwt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_addwt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesd.c similarity index 75% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesd.c index 5ea27aa3b768c5af517a3a1228b97693b09d9e1b..0839b32fecb78ea1bcc9a465f37c8157fe491e61 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesd.c +++ b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesd.c @@ -1,8 +1,8 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK // REQUIRES: aarch64-registered-target diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aese.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aese.c similarity index 75% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aese.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aese.c index 9442d14de83633b097ecbdca390a0918f3a1cb13..08ca748c96fe76b888feeb887c66edb4b921b7e1 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aese.c +++ b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aese.c @@ -1,8 +1,8 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK // REQUIRES: aarch64-registered-target diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesimc.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesimc.c similarity index 71% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesimc.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesimc.c index 23f838c5bb30ec95ad5d8dd8848fba763babe441..78d3debad4b34aa007a2263b9a824e129221b546 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesimc.c +++ b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesimc.c @@ -1,8 +1,8 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK // REQUIRES: aarch64-registered-target diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesmc.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesmc.c similarity index 71% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesmc.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesmc.c index 575c09c325f78f55c142bc1a5ea72adae08f7bbf..48d130174788ac5e64711d9898e2c0dd406b2810 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_aesmc.c +++ b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_aesmc.c @@ -1,8 +1,8 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK // REQUIRES: aarch64-registered-target diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bcax.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bcax.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bcax.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bcax.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bdep.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bdep.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bdep.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bdep.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bext.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bext.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bext.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bext.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bgrp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bgrp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bgrp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bgrp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bsl.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bsl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bsl.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bsl.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bsl1n.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bsl1n.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bsl1n.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bsl1n.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bsl2n.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bsl2n.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_bsl2n.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_bsl2n.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cdot.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cdot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cdot.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cdot.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cmla.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cmla.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cmla.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtlt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtlt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtlt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtlt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtx.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtx.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtx.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtx.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtxnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtxnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_cvtxnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_cvtxnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_eor3.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_eor3.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_eor3.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_eor3.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_eorbt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_eorbt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_eorbt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_eorbt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_eortb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_eortb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_eortb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_eortb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_faminmax.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_faminmax.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_faminmax.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_faminmax.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_hadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_hadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_hadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_hadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_histcnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_histcnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_histcnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_histcnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_histseg.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_histseg.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_histseg.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_histseg.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_hsub.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_hsub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_hsub.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_hsub.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_hsubr.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_hsubr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_hsubr.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_hsubr.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1sb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1sb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sh.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1sh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sh.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1sh.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sw.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1sw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1sw.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1sw.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1ub.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1ub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1ub.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1ub.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1uh.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1uh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1uh.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1uh.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1uw.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1uw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_ldnt1uw.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_ldnt1uw.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_logb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_logb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_logb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_logb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_luti.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_luti.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_luti.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_luti.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_match.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_match.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_match.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_match.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_maxnmp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_maxnmp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_maxnmp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_maxnmp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_maxp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_maxp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_maxp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_maxp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_minnmp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_minnmp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_minnmp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_minnmp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_minp.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_minp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_minp.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_minp.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mla.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mla.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mla.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlalb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlalb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlalb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlalb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlalt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlalt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlalt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlalt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mls.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mls.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mls.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mls.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlslb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlslb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlslb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlslb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlslt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlslt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mlslt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mlslt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_movlb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_movlb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_movlb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_movlb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_movlt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_movlt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_movlt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_movlt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mul.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mul.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mul.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mul.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mullb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mullb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mullb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mullb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mullt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mullt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_mullt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_mullt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_nbsl.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_nbsl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_nbsl.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_nbsl.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_nmatch.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_nmatch.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_nmatch.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_nmatch.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmul.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmul.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmul.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmul.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullb_128.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullb_128.c similarity index 85% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullb_128.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullb_128.c index a4935d8dadd542cd09b6a69553f8ba0a29a3319e..09583f98393a35f08e8c8cfbd53b2f4e377d91cc 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullb_128.c +++ b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullb_128.c @@ -1,10 +1,10 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK #include diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullt_128.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullt_128.c similarity index 85% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullt_128.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullt_128.c index a712a4f847f427a22f0822f2487d1f7dc98ce594..a4ffc3165ec8b1f4dd27dc646204df4df04d3681 100644 --- a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_pmullt_128.c +++ b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_pmullt_128.c @@ -1,10 +1,10 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve2-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fclang-abi-compat=latest -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -target-feature +sve2 -target-feature +sve-aes -O1 -Werror -Wall -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefix=CPP-CHECK #include diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qabs.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qabs.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qabs.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qabs.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qcadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qcadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qcadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qcadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlalb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlalb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlalb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlalb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlalbt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlalbt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlalbt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlalbt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlalt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlalt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlalt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlalt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlslb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlslb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlslb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlslb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlslbt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlslbt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlslbt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlslbt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlslt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlslt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmlslt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmlslt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmulh.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmulh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmulh.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmulh.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmullb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmullb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmullb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmullb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmullt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmullt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qdmullt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qdmullt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qneg.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qneg.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qneg.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qneg.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdcmlah.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdcmlah.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdcmlah.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdcmlah.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdmlah.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdmlah.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdmlah.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdmlah.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdmlsh.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdmlsh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdmlsh.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdmlsh.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdmulh.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdmulh.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrdmulh.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrdmulh.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshl.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshl.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshl.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrunb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrunb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrunb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrunb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrunt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrunt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qrshrunt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qrshrunt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshl.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshl.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshl.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshlu.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshlu.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrunb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrunb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrunb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrunb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrunt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrunt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshrunt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qshrunt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qsub.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qsub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qsub.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qsub.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qsubr.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qsubr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qsubr.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qsubr.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtunb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtunb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtunb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtunb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtunt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtunt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qxtunt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_qxtunt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_raddhnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_raddhnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_raddhnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_raddhnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_raddhnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_raddhnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_raddhnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_raddhnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rax1.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rax1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rax1.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rax1.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_recpe.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_recpe.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_recpe.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_recpe.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_revd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_revd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_revd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_revd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rhadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rhadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rhadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rhadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshl.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshl.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshl.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshr.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshr.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshr.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshrnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshrnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshrnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshrnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshrnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshrnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rshrnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rshrnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsqrte.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsqrte.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsqrte.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsqrte.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsra.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsra.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsra.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsra.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsubhnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsubhnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsubhnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsubhnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsubhnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsubhnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_rsubhnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_rsubhnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sbclb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sbclb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sbclb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sbclb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sbclt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sbclt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sbclt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sbclt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shllb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shllb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shllb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shllb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shllt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shllt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shllt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shllt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shrnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shrnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shrnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_shrnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sli.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sli.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sli.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sli.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sm4e.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sm4e.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sm4e.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sm4e.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sm4ekey.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sm4ekey.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sm4ekey.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sm4ekey.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sqadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sqadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sqadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sqadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sra.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sra.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sra.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sra.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sri.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sri.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sri.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sri.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1b.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1b.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1b.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1b.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1h.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1h.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1h.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1h.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1w.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1w.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_stnt1w.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_stnt1w.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subhnb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subhnb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subhnb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subhnb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subhnt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subhnt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subhnt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subhnt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sublb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sublb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sublb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sublb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sublbt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sublbt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sublbt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sublbt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sublt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sublt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_sublt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_sublt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subltb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subltb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subltb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subltb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subwb.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subwb.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subwb.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subwb.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subwt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subwt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_subwt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_subwt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbl2-bfloat.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbl2-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbl2-bfloat.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbl2-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbl2.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbl2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbl2.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbl2.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbx-bfloat.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbx-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbx-bfloat.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbx-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbx.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbx.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_tbx.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_tbx.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_uqadd.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_uqadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_uqadd.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_uqadd.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilege.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilege.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilege.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilege.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilegt.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilegt.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilegt.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilegt.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilerw-bfloat.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilerw-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilerw-bfloat.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilerw-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilerw.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilerw.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilerw.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilerw.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilewr-bfloat.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilewr-bfloat.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilewr-bfloat.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilewr-bfloat.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilewr.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilewr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_whilewr.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_whilewr.c diff --git a/clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_xar.c b/clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_xar.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_xar.c rename to clang/test/CodeGen/AArch64/sve2-intrinsics/acle_sve2_xar.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfadd.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfadd.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfadd.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfadd.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfclamp.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfclamp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfclamp.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfclamp.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmax.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmax.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmax.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmax.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmaxnm.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmin.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmin.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmin.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmin.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfminnm.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfminnm.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfminnm.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfminnm.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmla.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmla.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla_lane.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmla_lane.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmla_lane.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmla_lane.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmls.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmls.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls_lane.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmls_lane.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmls_lane.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmls_lane.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmlsl.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmlsl.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmlsl.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmlsl.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmul.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmul.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul_lane.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmul_lane.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfmul_lane.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfmul_lane.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfsub.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfsub.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_bfsub.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_bfsub.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_cntp.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_cntp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_cntp.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_cntp.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_create2_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create2_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_create2_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create4_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_create4_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_create4_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_create4_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dot.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_dot.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dot.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_dot.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dupq.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_dupq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dupq.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_dupq.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_extq.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_extq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_extq.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_extq.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_fclamp.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_fclamp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_fclamp.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_fclamp.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_fp_reduce.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_fp_reduce.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_fp_reduce.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_fp_reduce.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get2_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_get2_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get2_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_get2_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_get4_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_get4_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_get4_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_int_reduce.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_int_reduce.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_int_reduce.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_int_reduce.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ld1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ld1.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1_single.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ld1_single.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1_single.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ld1_single.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ldnt1.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ldnt1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ldnt1.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ldnt1.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_loads.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_loads.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_loads.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_loads.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pext.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pext.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pext.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pext.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pfalse.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pfalse.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pfalse.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pmov_to_pred.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pmov_to_pred.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pmov_to_pred.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pmov_to_pred.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pmov_to_vector.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pmov_to_vector.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_pmov_to_vector.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_pmov_to_vector.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_psel.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_psel.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel_svcount.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_psel_svcount.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_psel_svcount.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_psel_svcount.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ptrue.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ptrue.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ptrue.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_ptrue.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_qcvtn.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_qcvtn.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_qcvtn.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_qcvtn.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_qrshr.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_qrshr.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_qrshr.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_qrshr.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_sclamp.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_sclamp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_sclamp.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_sclamp.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set2_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_set2_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set2_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_set2_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set4_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_set4_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_set4_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_set4_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1_single.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_st1_single.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_stnt1.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_stnt1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_stnt1.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_stnt1.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_store.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_store.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_store.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_store.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_tblq.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_tblq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_tblq.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_tblq.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_tbxq.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_tbxq.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_tbxq.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_tbxq.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_uclamp.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_uclamp.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_uclamp.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_uclamp.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_undef_bool.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_undef_bool.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_undef_bool.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_undef_bool.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_uzpq1.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_uzpq1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_uzpq1.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_uzpq1.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_uzpq2.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_uzpq2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_uzpq2.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_uzpq2.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_while_pn.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_while_pn.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_while_pn.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_while_pn.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_while_x2.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_while_x2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_while_x2.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_while_x2.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_zipq1.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_zipq1.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_zipq1.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_zipq1.c diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_zipq2.c b/clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_zipq2.c similarity index 100% rename from clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_zipq2.c rename to clang/test/CodeGen/AArch64/sve2p1-intrinsics/acle_sve2p1_zipq2.c diff --git a/clang/test/CodeGen/aarch64-svepcs.c b/clang/test/CodeGen/AArch64/svepcs.c similarity index 100% rename from clang/test/CodeGen/aarch64-svepcs.c rename to clang/test/CodeGen/AArch64/svepcs.c diff --git a/clang/test/CodeGen/aarch64-sysregs-target.c b/clang/test/CodeGen/AArch64/sysregs-target.c similarity index 100% rename from clang/test/CodeGen/aarch64-sysregs-target.c rename to clang/test/CodeGen/AArch64/sysregs-target.c diff --git a/clang/test/CodeGen/aarch64-targetattr-arch.c b/clang/test/CodeGen/AArch64/targetattr-arch.c similarity index 100% rename from clang/test/CodeGen/aarch64-targetattr-arch.c rename to clang/test/CodeGen/AArch64/targetattr-arch.c diff --git a/clang/test/CodeGen/aarch64-targetattr-crypto.c b/clang/test/CodeGen/AArch64/targetattr-crypto.c similarity index 100% rename from clang/test/CodeGen/aarch64-targetattr-crypto.c rename to clang/test/CodeGen/AArch64/targetattr-crypto.c diff --git a/clang/test/CodeGen/aarch64-targetattr.c b/clang/test/CodeGen/AArch64/targetattr.c similarity index 96% rename from clang/test/CodeGen/aarch64-targetattr.c rename to clang/test/CodeGen/AArch64/targetattr.c index 1bc78a6e1f8c0f5c928efc49695744186de06fd1..ee7a07244ef9aad31938f2643d32741e4174f8db 100644 --- a/clang/test/CodeGen/aarch64-targetattr.c +++ b/clang/test/CodeGen/AArch64/targetattr.c @@ -210,8 +210,8 @@ void applem4() {} // CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "tune-cpu"="generic" } // CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fullfp16,+lse,+neon,+perfmon,+ras,+rcpc,+rdm,+sha2,+spe,+ssbs,+v8.1a,+v8.2a,+v8a" "tune-cpu"="cortex-a710" } // CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" "tune-cpu"="cortex-a710" } -// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" } -// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" } +// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+ccidx,+ccpp,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a" } +// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-v1" "target-features"="+aes,+bf16,+ccdp,+ccidx,+ccpp,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fp16fml,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+rand,+ras,+rcpc,+rdm,+sha2,+sha3,+sm4,+spe,+ssbs,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8a,-sve" } // CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+sve" } // CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16" } // CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="neoverse-n1" "target-features"="+aes,+bf16,+bti,+ccidx,+complxnum,+crc,+dit,+dotprod,+flagm,+fp-armv8,+fullfp16,+i8mm,+jsconv,+lse,+neon,+pauth,+perfmon,+predres,+ras,+rcpc,+rdm,+sb,+sha2,+spe,+ssbs,+sve,+sve2,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8.6a,+v8a" "tune-cpu"="cortex-a710" } diff --git a/clang/test/CodeGen/aarch64-tme.cpp b/clang/test/CodeGen/AArch64/tme.cpp similarity index 100% rename from clang/test/CodeGen/aarch64-tme.cpp rename to clang/test/CodeGen/AArch64/tme.cpp diff --git a/clang/test/CodeGen/aarch64-type-sizes.c b/clang/test/CodeGen/AArch64/type-sizes.c similarity index 100% rename from clang/test/CodeGen/aarch64-type-sizes.c rename to clang/test/CodeGen/AArch64/type-sizes.c diff --git a/clang/test/CodeGen/aarch64-v8.1a-neon-intrinsics.c b/clang/test/CodeGen/AArch64/v8.1a-neon-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.1a-neon-intrinsics.c rename to clang/test/CodeGen/AArch64/v8.1a-neon-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-v8.2a-fp16-intrinsics-constrained.c b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics-constrained.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.2a-fp16-intrinsics-constrained.c rename to clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics-constrained.c diff --git a/clang/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c b/clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.2a-fp16-intrinsics.c rename to clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-constrained.c b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-constrained.c rename to clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-constrained.c diff --git a/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-generic.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics-generic.c rename to clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics-generic.c diff --git a/clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c b/clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.2a-neon-intrinsics.c rename to clang/test/CodeGen/AArch64/v8.2a-neon-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-v8.5a-neon-frint3264-intrinsic.c b/clang/test/CodeGen/AArch64/v8.5a-neon-frint3264-intrinsic.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.5a-neon-frint3264-intrinsic.c rename to clang/test/CodeGen/AArch64/v8.5a-neon-frint3264-intrinsic.c diff --git a/clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c b/clang/test/CodeGen/AArch64/v8.5a-scalar-frint3264-intrinsic.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c rename to clang/test/CodeGen/AArch64/v8.5a-scalar-frint3264-intrinsic.c diff --git a/clang/test/CodeGen/aarch64-v8.6a-neon-intrinsics.c b/clang/test/CodeGen/AArch64/v8.6a-neon-intrinsics.c similarity index 100% rename from clang/test/CodeGen/aarch64-v8.6a-neon-intrinsics.c rename to clang/test/CodeGen/AArch64/v8.6a-neon-intrinsics.c diff --git a/clang/test/CodeGen/aarch64-varargs-ms.c b/clang/test/CodeGen/AArch64/varargs-ms.c similarity index 100% rename from clang/test/CodeGen/aarch64-varargs-ms.c rename to clang/test/CodeGen/AArch64/varargs-ms.c diff --git a/clang/test/CodeGen/aarch64-varargs-sve.c b/clang/test/CodeGen/AArch64/varargs-sve.c similarity index 100% rename from clang/test/CodeGen/aarch64-varargs-sve.c rename to clang/test/CodeGen/AArch64/varargs-sve.c diff --git a/clang/test/CodeGen/aarch64-varargs.c b/clang/test/CodeGen/AArch64/varargs.c similarity index 100% rename from clang/test/CodeGen/aarch64-varargs.c rename to clang/test/CodeGen/AArch64/varargs.c diff --git a/clang/test/CodeGen/aarch64-vpcs.c b/clang/test/CodeGen/AArch64/vpcs.c similarity index 100% rename from clang/test/CodeGen/aarch64-vpcs.c rename to clang/test/CodeGen/AArch64/vpcs.c diff --git a/clang/test/CodeGen/PowerPC/musttail-forward-declaration-inline.c b/clang/test/CodeGen/PowerPC/musttail-forward-declaration-inline.c index 3d8ff3985cb0f5e951f7e57142bb564e83168d08..d0ec21209582ee42c88ef10b7dc616e017479cef 100644 --- a/clang/test/CodeGen/PowerPC/musttail-forward-declaration-inline.c +++ b/clang/test/CodeGen/PowerPC/musttail-forward-declaration-inline.c @@ -3,7 +3,7 @@ inline int func2(int i); int external_call2(int i) { - // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls can not be tail called on PPC}} + // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls cannot be tail called on PPC}} [[clang::musttail]] return func2(i); } diff --git a/clang/test/CodeGen/PowerPC/musttail-forward-declaration-weak.c b/clang/test/CodeGen/PowerPC/musttail-forward-declaration-weak.c index 4314bbdd30619ece3139400ff3d7d7f0e638a591..57226d2109f325ca4f7e406bc6cce6ed2464d57f 100644 --- a/clang/test/CodeGen/PowerPC/musttail-forward-declaration-weak.c +++ b/clang/test/CodeGen/PowerPC/musttail-forward-declaration-weak.c @@ -3,7 +3,7 @@ int func2(int i); int external_call2(int i) { - // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls can not be tail called on PPC}} + // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls cannot be tail called on PPC}} [[clang::musttail]] return func2(i); } diff --git a/clang/test/CodeGen/PowerPC/musttail-indirect.cpp b/clang/test/CodeGen/PowerPC/musttail-indirect.cpp index 3f495002606d47d3e9b3dddd5a006a89772215b4..cc506d4f7bc1f1f1785ac069abf485ac921dcef0 100644 --- a/clang/test/CodeGen/PowerPC/musttail-indirect.cpp +++ b/clang/test/CodeGen/PowerPC/musttail-indirect.cpp @@ -3,6 +3,6 @@ void name(int *params) { auto fn = (void (*)(int *))1; - // expected-error@+1 {{'musttail' attribute for this call is impossible because indirect calls can not be tail called on PPC}} + // expected-error@+1 {{'musttail' attribute for this call is impossible because indirect calls cannot be tail called on PPC}} [[clang::musttail]] return fn(params); } diff --git a/clang/test/CodeGen/PowerPC/musttail-inline.c b/clang/test/CodeGen/PowerPC/musttail-inline.c index 05aac88697127446016d974893c9c6094befb1a9..1ac841f088cf555e297837b0ba23aa0852db87ff 100644 --- a/clang/test/CodeGen/PowerPC/musttail-inline.c +++ b/clang/test/CodeGen/PowerPC/musttail-inline.c @@ -7,6 +7,6 @@ inline int foo(int x) { int bar(int x) { - // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls can not be tail called on PPC}} + // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls cannot be tail called on PPC}} [[clang::musttail]] return foo(1); } diff --git a/clang/test/CodeGen/PowerPC/musttail-undefined.c b/clang/test/CodeGen/PowerPC/musttail-undefined.c index f2259adb01848252a97b27c9a2339e9e4f3f8e06..fb3845218a622535b943ff260f5d1fe59ce27c78 100644 --- a/clang/test/CodeGen/PowerPC/musttail-undefined.c +++ b/clang/test/CodeGen/PowerPC/musttail-undefined.c @@ -5,6 +5,6 @@ int foo(int x); int bar(int x) { - // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls can not be tail called on PPC}} + // expected-error@+1 {{'musttail' attribute for this call is impossible because external calls cannot be tail called on PPC}} [[clang::musttail]] return foo(x); } diff --git a/clang/test/CodeGen/PowerPC/musttail-weak.c b/clang/test/CodeGen/PowerPC/musttail-weak.c index dccc7a4d8cdd2cbc9a9348718e3237264928f91f..1070b91bc5f35d75a9d4a695d2f877bd5a5f2047 100644 --- a/clang/test/CodeGen/PowerPC/musttail-weak.c +++ b/clang/test/CodeGen/PowerPC/musttail-weak.c @@ -7,7 +7,7 @@ __attribute__((weak)) int func2(int i) { return 0; } int external_call2(int i) { - // linux-error@+2 {{'musttail' attribute for this call is impossible because external calls can not be tail called on PPC}} + // linux-error@+2 {{'musttail' attribute for this call is impossible because external calls cannot be tail called on PPC}} // aix-error@+1 {{'musttail' attribute is not supported on AIX}} [[clang::musttail]] return func2(i); } diff --git a/clang/test/CodeGen/PowerPC/musttail.c b/clang/test/CodeGen/PowerPC/musttail.c index e3129263d2460161001b89e26b6171ca3c4e3a70..7a74d084c67be0ece2bfd915238828466606458d 100644 --- a/clang/test/CodeGen/PowerPC/musttail.c +++ b/clang/test/CodeGen/PowerPC/musttail.c @@ -14,7 +14,7 @@ int foo(int x) { int bar(int x) { // good-no-diagnostics - // longcall-error@+2 {{'musttail' attribute for this call is impossible because long calls can not be tail called on PPC}} + // longcall-error@+2 {{'musttail' attribute for this call is impossible because long calls cannot be tail called on PPC}} // aix-error@+1 {{'musttail' attribute is not supported on AIX}} [[clang::musttail]] return foo(1); } diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index 75b91d3c497c5097ab6b6ad8545490d512b4230f..de90e513ea1ff1b342505f72a9b24a32d062ee62 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -33,6 +33,19 @@ void test_cf(float f, double d) { asm volatile("" : "=cf"(cd) : "cf"(d)); } +#if __riscv_xlen == 32 +typedef long long double_xlen_t; +#elif __riscv_xlen == 64 +typedef __int128_t double_xlen_t; +#endif +double_xlen_t test_R_wide_scalar(double_xlen_t p) { +// CHECK-LABEL: define{{.*}} {{i128|i64}} @test_R_wide_scalar( +// CHECK: call {{i128|i64}} asm sideeffect "", "=R,R"({{i128|i64}} %{{.*}}) + double_xlen_t ret; + asm volatile("" : "=R"(ret) : "R"(p)); + return ret; +} + void test_I(void) { // CHECK-LABEL: define{{.*}} void @test_I() // CHECK: call void asm sideeffect "", "I"(i32 2047) diff --git a/clang/test/CodeGen/SystemZ/systemz-inline-asm.c b/clang/test/CodeGen/SystemZ/systemz-inline-asm.c index e38d37cd345e2613785dda6b2572826d69f52a39..2a9d6a5f8745480a43e2a686767f22e03d8e11d1 100644 --- a/clang/test/CodeGen/SystemZ/systemz-inline-asm.c +++ b/clang/test/CodeGen/SystemZ/systemz-inline-asm.c @@ -123,7 +123,7 @@ double test_f64(double f, double g) { long double test_f128(long double f, long double g) { asm("axbr %0, %2" : "=f" (f) : "0" (f), "f" (g)); return f; -// CHECK: define{{.*}} void @test_f128(ptr dead_on_unwind noalias nocapture writable writeonly sret(fp128) align 8 [[DEST:%.*]], ptr nocapture noundef readonly %0, ptr nocapture noundef readonly %1) +// CHECK: define{{.*}} void @test_f128(ptr dead_on_unwind noalias nocapture writable writeonly sret(fp128) align 8 initializes((0, 16)) [[DEST:%.*]], ptr nocapture noundef readonly %0, ptr nocapture noundef readonly %1) // CHECK: %f = load fp128, ptr %0 // CHECK: %g = load fp128, ptr %1 // CHECK: [[RESULT:%.*]] = tail call fp128 asm "axbr $0, $2", "=f,0,f"(fp128 %f, fp128 %g) diff --git a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c index 6194c9b1804fb0b4888744664259515e60f6a402..82bb7a52d05d11a4d3e61763e5a15bf3888a4a7a 100644 --- a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c +++ b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c @@ -12,42 +12,42 @@ struct Foo { void use_foo(struct Foo *f); void ptr32_to_ptr(struct Foo *f, int * __ptr32 i) { - // X64-LABEL: define void @ptr32_to_ptr(ptr noundef %f, ptr addrspace(1) noundef %i) + // X64-LABEL: define void @ptr32_to_ptr(ptr noundef initializes((8, 16)) %f, ptr addrspace(1) noundef %i) // X64: %{{.+}} = addrspacecast ptr addrspace(1) %i to ptr f->p64= i; use_foo(f); } void ptr_to_ptr32(struct Foo *f, int *i) { - // X64-LABEL: define void @ptr_to_ptr32(ptr noundef %f, ptr noundef %i) + // X64-LABEL: define void @ptr_to_ptr32(ptr noundef initializes((0, 4)) %f, ptr noundef %i) // X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(1) f->p32 = i; use_foo(f); } void ptr32_to_ptr32(struct Foo *f, int * __ptr32 i) { - // X64-LABEL: define void @ptr32_to_ptr32(ptr noundef %f, ptr addrspace(1) noundef %i) + // X64-LABEL: define void @ptr32_to_ptr32(ptr noundef initializes((0, 4)) %f, ptr addrspace(1) noundef %i) // X64-NOT: addrspacecast f->p32 = i; use_foo(f); } void ptr_to_ptr32_explicit_cast(struct Foo *f, int *i) { - // X64-LABEL: define void @ptr_to_ptr32_explicit_cast(ptr noundef %f, ptr noundef %i) + // X64-LABEL: define void @ptr_to_ptr32_explicit_cast(ptr noundef initializes((0, 4)) %f, ptr noundef %i) // X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(1) f->p32 = (int * __ptr32)i; use_foo(f); } void test_indexing(struct Foo *f) { - // X64-LABEL: define void @test_indexing(ptr noundef %f) + // X64-LABEL: define void @test_indexing(ptr noundef initializes((16, 24)) %f) // X64: addrspacecast ptr addrspace(1) {{%[0-9]}} to ptr f->cp64 = ((char * __ptr32 *)1028)[1]; use_foo(f); } void test_indexing_2(struct Foo *f) { - // X64-LABEL: define void @test_indexing_2(ptr noundef %f) + // X64-LABEL: define void @test_indexing_2(ptr noundef initializes((16, 24)) %f) // X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 16 // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 24 f->cp64 = ((char *** __ptr32 *)1028)[1][2][3]; @@ -108,7 +108,7 @@ int test_misc_4() { } void test_misc_5(struct Foo *f) { - // X64-LABEL: define void @test_misc_5(ptr noundef %f) + // X64-LABEL: define void @test_misc_5(ptr noundef initializes((16, 24)) %f) // X64: addrspacecast ptr addrspace(1) %0 to ptr f->cp64 = *(char* __ptr32 *)(PSA_PTR + PSAAOLD); use_foo(f); diff --git a/clang/test/CodeGen/SystemZ/zvector.c b/clang/test/CodeGen/SystemZ/zvector.c index 4b28e394b33b724b4b5e802aca974539aa372000..cbf6a9a1a1bf2ad784b62abdbb00892c978f8d67 100644 --- a/clang/test/CodeGen/SystemZ/zvector.c +++ b/clang/test/CodeGen/SystemZ/zvector.c @@ -1,3 +1,4 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // RUN: %clang_cc1 -triple s390x-linux-gnu -target-cpu z13 -fzvector \ // RUN: -emit-llvm -o - -W -Wall -Werror \ // RUN: %s | opt -S -passes=mem2reg | FileCheck %s @@ -22,26 +23,29 @@ volatile vector double fd, fd2; volatile int cnt; -// CHECK-LABEL: define{{.*}} void @test_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: store volatile <16 x i8> [[TMP0]], ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: store volatile <16 x i8> [[TMP1]], ptr @uc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: store volatile <8 x i16> [[TMP2]], ptr @ss, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: store volatile <8 x i16> [[TMP3]], ptr @us, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: store volatile <4 x i32> [[TMP4]], ptr @si, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: store volatile <4 x i32> [[TMP5]], ptr @ui, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: store volatile <2 x i64> [[TMP6]], ptr @sl, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: store volatile <2 x i64> [[TMP7]], ptr @ul, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: store volatile <2 x double> [[TMP8]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_assign( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: store volatile <16 x i8> [[TMP0]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: store volatile <16 x i8> [[TMP1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: store volatile <8 x i16> [[TMP2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: store volatile <8 x i16> [[TMP3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: store volatile <4 x i32> [[TMP4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: store volatile <4 x i32> [[TMP5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: store volatile <2 x i64> [[TMP6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: store volatile <2 x i64> [[TMP7]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: store volatile <2 x double> [[TMP8]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_assign(void) { sc = sc2; @@ -59,26 +63,29 @@ void test_assign(void) { fd = fd2; } -// CHECK-LABEL: define{{.*}} void @test_pos() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: store volatile <16 x i8> [[TMP0]], ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: store volatile <16 x i8> [[TMP1]], ptr @uc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: store volatile <8 x i16> [[TMP2]], ptr @ss, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: store volatile <8 x i16> [[TMP3]], ptr @us, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: store volatile <4 x i32> [[TMP4]], ptr @si, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: store volatile <4 x i32> [[TMP5]], ptr @ui, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: store volatile <2 x i64> [[TMP6]], ptr @sl, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: store volatile <2 x i64> [[TMP7]], ptr @ul, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: store volatile <2 x double> [[TMP8]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_pos( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: store volatile <16 x i8> [[TMP0]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: store volatile <16 x i8> [[TMP1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: store volatile <8 x i16> [[TMP2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: store volatile <8 x i16> [[TMP3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: store volatile <4 x i32> [[TMP4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: store volatile <4 x i32> [[TMP5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: store volatile <2 x i64> [[TMP6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: store volatile <2 x i64> [[TMP7]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: store volatile <2 x double> [[TMP8]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_pos(void) { sc = +sc2; @@ -96,23 +103,26 @@ void test_pos(void) { fd = +fd2; } -// CHECK-LABEL: define{{.*}} void @test_neg() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SUB:%.*]] = sub <16 x i8> zeroinitializer, [[TMP0]] -// CHECK: store volatile <16 x i8> [[SUB]], ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SUB1:%.*]] = sub <8 x i16> zeroinitializer, [[TMP1]] -// CHECK: store volatile <8 x i16> [[SUB1]], ptr @ss, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SUB2:%.*]] = sub <4 x i32> zeroinitializer, [[TMP2]] -// CHECK: store volatile <4 x i32> [[SUB2]], ptr @si, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SUB3:%.*]] = sub <2 x i64> zeroinitializer, [[TMP3]] -// CHECK: store volatile <2 x i64> [[SUB3]], ptr @sl, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[SUB4:%.*]] = fneg <2 x double> [[TMP4]] -// CHECK: store volatile <2 x double> [[SUB4]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_neg( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i8> zeroinitializer, [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SUB1:%.*]] = sub <8 x i16> zeroinitializer, [[TMP1]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB1]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SUB2:%.*]] = sub <4 x i32> zeroinitializer, [[TMP2]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB2]], ptr @si, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SUB3:%.*]] = sub <2 x i64> zeroinitializer, [[TMP3]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB3]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[FNEG:%.*]] = fneg <2 x double> [[TMP4]] +// CHECK-NEXT: store volatile <2 x double> [[FNEG]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_neg(void) { sc = -sc2; @@ -122,35 +132,38 @@ void test_neg(void) { fd = -fd2; } -// CHECK-LABEL: define{{.*}} void @test_preinc() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[INC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 1) -// CHECK: store volatile <16 x i8> [[INC]], ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[INC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 1) -// CHECK: store volatile <16 x i8> [[INC1]], ptr @uc2, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[INC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 1) -// CHECK: store volatile <8 x i16> [[INC2]], ptr @ss2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[INC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 1) -// CHECK: store volatile <8 x i16> [[INC3]], ptr @us2, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[INC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 1) -// CHECK: store volatile <4 x i32> [[INC4]], ptr @si2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[INC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 1) -// CHECK: store volatile <4 x i32> [[INC5]], ptr @ui2, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[INC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 1) -// CHECK: store volatile <2 x i64> [[INC6]], ptr @sl2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[INC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 1) -// CHECK: store volatile <2 x i64> [[INC7]], ptr @ul2, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[INC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double 1.000000e+00) -// CHECK: store volatile <2 x double> [[INC8]], ptr @fd2, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_preinc( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[INC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 1) +// CHECK-NEXT: store volatile <16 x i8> [[INC]], ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[INC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 1) +// CHECK-NEXT: store volatile <16 x i8> [[INC1]], ptr @uc2, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[INC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 1) +// CHECK-NEXT: store volatile <8 x i16> [[INC2]], ptr @ss2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[INC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 1) +// CHECK-NEXT: store volatile <8 x i16> [[INC3]], ptr @us2, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[INC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 1) +// CHECK-NEXT: store volatile <4 x i32> [[INC4]], ptr @si2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[INC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 1) +// CHECK-NEXT: store volatile <4 x i32> [[INC5]], ptr @ui2, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[INC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 1) +// CHECK-NEXT: store volatile <2 x i64> [[INC6]], ptr @sl2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[INC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 1) +// CHECK-NEXT: store volatile <2 x i64> [[INC7]], ptr @ul2, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[INC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double 1.000000e+00) +// CHECK-NEXT: store volatile <2 x double> [[INC8]], ptr @fd2, align 8 +// CHECK-NEXT: ret void +// void test_preinc(void) { ++sc2; @@ -168,35 +181,38 @@ void test_preinc(void) { ++fd2; } -// CHECK-LABEL: define{{.*}} void @test_postinc() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[INC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 1) -// CHECK: store volatile <16 x i8> [[INC]], ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[INC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 1) -// CHECK: store volatile <16 x i8> [[INC1]], ptr @uc2, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[INC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 1) -// CHECK: store volatile <8 x i16> [[INC2]], ptr @ss2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[INC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 1) -// CHECK: store volatile <8 x i16> [[INC3]], ptr @us2, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[INC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 1) -// CHECK: store volatile <4 x i32> [[INC4]], ptr @si2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[INC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 1) -// CHECK: store volatile <4 x i32> [[INC5]], ptr @ui2, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[INC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 1) -// CHECK: store volatile <2 x i64> [[INC6]], ptr @sl2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[INC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 1) -// CHECK: store volatile <2 x i64> [[INC7]], ptr @ul2, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[INC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double 1.000000e+00) -// CHECK: store volatile <2 x double> [[INC8]], ptr @fd2, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_postinc( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[INC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 1) +// CHECK-NEXT: store volatile <16 x i8> [[INC]], ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[INC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 1) +// CHECK-NEXT: store volatile <16 x i8> [[INC1]], ptr @uc2, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[INC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 1) +// CHECK-NEXT: store volatile <8 x i16> [[INC2]], ptr @ss2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[INC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 1) +// CHECK-NEXT: store volatile <8 x i16> [[INC3]], ptr @us2, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[INC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 1) +// CHECK-NEXT: store volatile <4 x i32> [[INC4]], ptr @si2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[INC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 1) +// CHECK-NEXT: store volatile <4 x i32> [[INC5]], ptr @ui2, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[INC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 1) +// CHECK-NEXT: store volatile <2 x i64> [[INC6]], ptr @sl2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[INC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 1) +// CHECK-NEXT: store volatile <2 x i64> [[INC7]], ptr @ul2, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[INC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double 1.000000e+00) +// CHECK-NEXT: store volatile <2 x double> [[INC8]], ptr @fd2, align 8 +// CHECK-NEXT: ret void +// void test_postinc(void) { sc2++; @@ -214,35 +230,38 @@ void test_postinc(void) { fd2++; } -// CHECK-LABEL: define{{.*}} void @test_predec() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[DEC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[DEC]], ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[DEC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[DEC1]], ptr @uc2, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[DEC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[DEC2]], ptr @ss2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[DEC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[DEC3]], ptr @us2, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[DEC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[DEC4]], ptr @si2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[DEC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[DEC5]], ptr @ui2, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[DEC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[DEC6]], ptr @sl2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[DEC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[DEC7]], ptr @ul2, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[DEC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double -1.000000e+00) -// CHECK: store volatile <2 x double> [[DEC8]], ptr @fd2, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_predec( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[DEC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[DEC]], ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[DEC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[DEC1]], ptr @uc2, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[DEC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[DEC2]], ptr @ss2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[DEC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[DEC3]], ptr @us2, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[DEC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[DEC4]], ptr @si2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[DEC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[DEC5]], ptr @ui2, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[DEC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[DEC6]], ptr @sl2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[DEC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[DEC7]], ptr @ul2, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[DEC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double -1.000000e+00) +// CHECK-NEXT: store volatile <2 x double> [[DEC8]], ptr @fd2, align 8 +// CHECK-NEXT: ret void +// void test_predec(void) { --sc2; @@ -260,35 +279,38 @@ void test_predec(void) { --fd2; } -// CHECK-LABEL: define{{.*}} void @test_postdec() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[DEC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[DEC]], ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[DEC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[DEC1]], ptr @uc2, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[DEC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[DEC2]], ptr @ss2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[DEC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[DEC3]], ptr @us2, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[DEC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[DEC4]], ptr @si2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[DEC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[DEC5]], ptr @ui2, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[DEC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[DEC6]], ptr @sl2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[DEC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[DEC7]], ptr @ul2, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[DEC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double -1.000000e+00) -// CHECK: store volatile <2 x double> [[DEC8]], ptr @fd2, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_postdec( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[DEC:%.*]] = add <16 x i8> [[TMP0]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[DEC]], ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[DEC1:%.*]] = add <16 x i8> [[TMP1]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[DEC1]], ptr @uc2, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[DEC2:%.*]] = add <8 x i16> [[TMP2]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[DEC2]], ptr @ss2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[DEC3:%.*]] = add <8 x i16> [[TMP3]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[DEC3]], ptr @us2, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[DEC4:%.*]] = add <4 x i32> [[TMP4]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[DEC4]], ptr @si2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[DEC5:%.*]] = add <4 x i32> [[TMP5]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[DEC5]], ptr @ui2, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[DEC6:%.*]] = add <2 x i64> [[TMP6]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[DEC6]], ptr @sl2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[DEC7:%.*]] = add <2 x i64> [[TMP7]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[DEC7]], ptr @ul2, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[DEC8:%.*]] = fadd <2 x double> [[TMP8]], splat (double -1.000000e+00) +// CHECK-NEXT: store volatile <2 x double> [[DEC8]], ptr @fd2, align 8 +// CHECK-NEXT: ret void +// void test_postdec(void) { sc2--; @@ -306,108 +328,111 @@ void test_postdec(void) { fd2--; } -// CHECK-LABEL: define{{.*}} void @test_add() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[ADD:%.*]] = add <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[ADD]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[ADD1:%.*]] = add <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[ADD1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[ADD2:%.*]] = add <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: store volatile <16 x i8> [[ADD2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[ADD3:%.*]] = add <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[ADD3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[ADD4:%.*]] = add <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[ADD4]], ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[ADD5:%.*]] = add <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: store volatile <16 x i8> [[ADD5]], ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[ADD6:%.*]] = add <8 x i16> [[TMP12]], [[TMP13]] -// CHECK: store volatile <8 x i16> [[ADD6]], ptr @ss, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[ADD7:%.*]] = add <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[ADD7]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[ADD8:%.*]] = add <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[ADD8]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[ADD9:%.*]] = add <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: store volatile <8 x i16> [[ADD9]], ptr @us, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[ADD10:%.*]] = add <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[ADD10]], ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[ADD11:%.*]] = add <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[ADD11]], ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[ADD12:%.*]] = add <4 x i32> [[TMP24]], [[TMP25]] -// CHECK: store volatile <4 x i32> [[ADD12]], ptr @si, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[ADD13:%.*]] = add <4 x i32> [[TMP26]], [[TMP27]] -// CHECK: store volatile <4 x i32> [[ADD13]], ptr @si, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[ADD14:%.*]] = add <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[ADD14]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[ADD15:%.*]] = add <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[ADD15]], ptr @ui, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[ADD16:%.*]] = add <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: store volatile <4 x i32> [[ADD16]], ptr @ui, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[ADD17:%.*]] = add <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[ADD17]], ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[ADD18:%.*]] = add <2 x i64> [[TMP36]], [[TMP37]] -// CHECK: store volatile <2 x i64> [[ADD18]], ptr @sl, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[ADD19:%.*]] = add <2 x i64> [[TMP38]], [[TMP39]] -// CHECK: store volatile <2 x i64> [[ADD19]], ptr @sl, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[ADD20:%.*]] = add <2 x i64> [[TMP40]], [[TMP41]] -// CHECK: store volatile <2 x i64> [[ADD20]], ptr @sl, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[ADD21:%.*]] = add <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[ADD21]], ptr @ul, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[ADD22:%.*]] = add <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[ADD22]], ptr @ul, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[ADD23:%.*]] = add <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: store volatile <2 x i64> [[ADD23]], ptr @ul, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[ADD24:%.*]] = fadd <2 x double> [[TMP48]], [[TMP49]] -// CHECK: store volatile <2 x double> [[ADD24]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_add( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[ADD1:%.*]] = add <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[ADD2:%.*]] = add <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[ADD3:%.*]] = add <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[ADD4:%.*]] = add <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[ADD5:%.*]] = add <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[ADD6:%.*]] = add <8 x i16> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD6]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[ADD7:%.*]] = add <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD7]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[ADD8:%.*]] = add <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD8]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[ADD9:%.*]] = add <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD9]], ptr @us, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[ADD10:%.*]] = add <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD10]], ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[ADD11:%.*]] = add <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD11]], ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[ADD12:%.*]] = add <4 x i32> [[TMP24]], [[TMP25]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD12]], ptr @si, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[ADD13:%.*]] = add <4 x i32> [[TMP26]], [[TMP27]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD13]], ptr @si, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[ADD14:%.*]] = add <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD14]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[ADD15:%.*]] = add <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD15]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[ADD16:%.*]] = add <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD16]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[ADD17:%.*]] = add <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD17]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[ADD18:%.*]] = add <2 x i64> [[TMP36]], [[TMP37]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD18]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[ADD19:%.*]] = add <2 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD19]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[ADD20:%.*]] = add <2 x i64> [[TMP40]], [[TMP41]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD20]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[ADD21:%.*]] = add <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD21]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[ADD22:%.*]] = add <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD22]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[ADD23:%.*]] = add <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD23]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[ADD24:%.*]] = fadd <2 x double> [[TMP48]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x double> [[ADD24]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_add(void) { sc = sc + sc2; @@ -441,76 +466,79 @@ void test_add(void) { fd = fd + fd2; } -// CHECK-LABEL: define{{.*}} void @test_add_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[ADD:%.*]] = add <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[ADD]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[ADD1:%.*]] = add <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[ADD1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[ADD2:%.*]] = add <16 x i8> [[TMP5]], [[TMP4]] -// CHECK: store volatile <16 x i8> [[ADD2]], ptr @uc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[ADD3:%.*]] = add <16 x i8> [[TMP7]], [[TMP6]] -// CHECK: store volatile <16 x i8> [[ADD3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[ADD4:%.*]] = add <8 x i16> [[TMP9]], [[TMP8]] -// CHECK: store volatile <8 x i16> [[ADD4]], ptr @ss, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[ADD5:%.*]] = add <8 x i16> [[TMP11]], [[TMP10]] -// CHECK: store volatile <8 x i16> [[ADD5]], ptr @ss, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[ADD6:%.*]] = add <8 x i16> [[TMP13]], [[TMP12]] -// CHECK: store volatile <8 x i16> [[ADD6]], ptr @us, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[ADD7:%.*]] = add <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[ADD7]], ptr @us, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[ADD8:%.*]] = add <4 x i32> [[TMP17]], [[TMP16]] -// CHECK: store volatile <4 x i32> [[ADD8]], ptr @si, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[ADD9:%.*]] = add <4 x i32> [[TMP19]], [[TMP18]] -// CHECK: store volatile <4 x i32> [[ADD9]], ptr @si, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[ADD10:%.*]] = add <4 x i32> [[TMP21]], [[TMP20]] -// CHECK: store volatile <4 x i32> [[ADD10]], ptr @ui, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[ADD11:%.*]] = add <4 x i32> [[TMP23]], [[TMP22]] -// CHECK: store volatile <4 x i32> [[ADD11]], ptr @ui, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[ADD12:%.*]] = add <2 x i64> [[TMP25]], [[TMP24]] -// CHECK: store volatile <2 x i64> [[ADD12]], ptr @sl, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[ADD13:%.*]] = add <2 x i64> [[TMP27]], [[TMP26]] -// CHECK: store volatile <2 x i64> [[ADD13]], ptr @sl, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[ADD14:%.*]] = add <2 x i64> [[TMP29]], [[TMP28]] -// CHECK: store volatile <2 x i64> [[ADD14]], ptr @ul, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[ADD15:%.*]] = add <2 x i64> [[TMP31]], [[TMP30]] -// CHECK: store volatile <2 x i64> [[ADD15]], ptr @ul, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[ADD16:%.*]] = fadd <2 x double> [[TMP33]], [[TMP32]] -// CHECK: store volatile <2 x double> [[ADD16]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_add_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[ADD:%.*]] = add <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[ADD1:%.*]] = add <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[ADD2:%.*]] = add <16 x i8> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD2]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[ADD3:%.*]] = add <16 x i8> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <16 x i8> [[ADD3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[ADD4:%.*]] = add <8 x i16> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD4]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[ADD5:%.*]] = add <8 x i16> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD5]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[ADD6:%.*]] = add <8 x i16> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD6]], ptr @us, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[ADD7:%.*]] = add <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[ADD7]], ptr @us, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[ADD8:%.*]] = add <4 x i32> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD8]], ptr @si, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[ADD9:%.*]] = add <4 x i32> [[TMP19]], [[TMP18]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD9]], ptr @si, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[ADD10:%.*]] = add <4 x i32> [[TMP21]], [[TMP20]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD10]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[ADD11:%.*]] = add <4 x i32> [[TMP23]], [[TMP22]] +// CHECK-NEXT: store volatile <4 x i32> [[ADD11]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[ADD12:%.*]] = add <2 x i64> [[TMP25]], [[TMP24]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD12]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[ADD13:%.*]] = add <2 x i64> [[TMP27]], [[TMP26]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD13]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[ADD14:%.*]] = add <2 x i64> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD14]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[ADD15:%.*]] = add <2 x i64> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <2 x i64> [[ADD15]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[ADD16:%.*]] = fadd <2 x double> [[TMP33]], [[TMP32]] +// CHECK-NEXT: store volatile <2 x double> [[ADD16]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_add_assign(void) { sc += sc2; @@ -536,108 +564,111 @@ void test_add_assign(void) { fd += fd2; } -// CHECK-LABEL: define{{.*}} void @test_sub() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SUB:%.*]] = sub <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[SUB]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[SUB1:%.*]] = sub <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[SUB1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SUB2:%.*]] = sub <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: store volatile <16 x i8> [[SUB2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[SUB3:%.*]] = sub <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[SUB3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[SUB4:%.*]] = sub <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[SUB4]], ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[SUB5:%.*]] = sub <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: store volatile <16 x i8> [[SUB5]], ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SUB6:%.*]] = sub <8 x i16> [[TMP12]], [[TMP13]] -// CHECK: store volatile <8 x i16> [[SUB6]], ptr @ss, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[SUB7:%.*]] = sub <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[SUB7]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SUB8:%.*]] = sub <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[SUB8]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[SUB9:%.*]] = sub <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: store volatile <8 x i16> [[SUB9]], ptr @us, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[SUB10:%.*]] = sub <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[SUB10]], ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[SUB11:%.*]] = sub <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[SUB11]], ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SUB12:%.*]] = sub <4 x i32> [[TMP24]], [[TMP25]] -// CHECK: store volatile <4 x i32> [[SUB12]], ptr @si, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[SUB13:%.*]] = sub <4 x i32> [[TMP26]], [[TMP27]] -// CHECK: store volatile <4 x i32> [[SUB13]], ptr @si, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SUB14:%.*]] = sub <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[SUB14]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[SUB15:%.*]] = sub <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[SUB15]], ptr @ui, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[SUB16:%.*]] = sub <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: store volatile <4 x i32> [[SUB16]], ptr @ui, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[SUB17:%.*]] = sub <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[SUB17]], ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SUB18:%.*]] = sub <2 x i64> [[TMP36]], [[TMP37]] -// CHECK: store volatile <2 x i64> [[SUB18]], ptr @sl, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[SUB19:%.*]] = sub <2 x i64> [[TMP38]], [[TMP39]] -// CHECK: store volatile <2 x i64> [[SUB19]], ptr @sl, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SUB20:%.*]] = sub <2 x i64> [[TMP40]], [[TMP41]] -// CHECK: store volatile <2 x i64> [[SUB20]], ptr @sl, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[SUB21:%.*]] = sub <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[SUB21]], ptr @ul, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[SUB22:%.*]] = sub <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[SUB22]], ptr @ul, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[SUB23:%.*]] = sub <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: store volatile <2 x i64> [[SUB23]], ptr @ul, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[SUB24:%.*]] = fsub <2 x double> [[TMP48]], [[TMP49]] -// CHECK: store volatile <2 x double> [[SUB24]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_sub( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[SUB1:%.*]] = sub <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SUB2:%.*]] = sub <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[SUB3:%.*]] = sub <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[SUB4:%.*]] = sub <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[SUB5:%.*]] = sub <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SUB6:%.*]] = sub <8 x i16> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB6]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[SUB7:%.*]] = sub <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB7]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SUB8:%.*]] = sub <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB8]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[SUB9:%.*]] = sub <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB9]], ptr @us, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[SUB10:%.*]] = sub <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB10]], ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[SUB11:%.*]] = sub <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB11]], ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SUB12:%.*]] = sub <4 x i32> [[TMP24]], [[TMP25]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB12]], ptr @si, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[SUB13:%.*]] = sub <4 x i32> [[TMP26]], [[TMP27]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB13]], ptr @si, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SUB14:%.*]] = sub <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB14]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[SUB15:%.*]] = sub <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB15]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[SUB16:%.*]] = sub <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB16]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[SUB17:%.*]] = sub <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB17]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SUB18:%.*]] = sub <2 x i64> [[TMP36]], [[TMP37]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB18]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[SUB19:%.*]] = sub <2 x i64> [[TMP38]], [[TMP39]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB19]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SUB20:%.*]] = sub <2 x i64> [[TMP40]], [[TMP41]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB20]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[SUB21:%.*]] = sub <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB21]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[SUB22:%.*]] = sub <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB22]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[SUB23:%.*]] = sub <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB23]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[SUB24:%.*]] = fsub <2 x double> [[TMP48]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x double> [[SUB24]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_sub(void) { sc = sc - sc2; @@ -671,76 +702,79 @@ void test_sub(void) { fd = fd - fd2; } -// CHECK-LABEL: define{{.*}} void @test_sub_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SUB:%.*]] = sub <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[SUB]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SUB1:%.*]] = sub <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[SUB1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SUB2:%.*]] = sub <16 x i8> [[TMP5]], [[TMP4]] -// CHECK: store volatile <16 x i8> [[SUB2]], ptr @uc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SUB3:%.*]] = sub <16 x i8> [[TMP7]], [[TMP6]] -// CHECK: store volatile <16 x i8> [[SUB3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SUB4:%.*]] = sub <8 x i16> [[TMP9]], [[TMP8]] -// CHECK: store volatile <8 x i16> [[SUB4]], ptr @ss, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SUB5:%.*]] = sub <8 x i16> [[TMP11]], [[TMP10]] -// CHECK: store volatile <8 x i16> [[SUB5]], ptr @ss, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SUB6:%.*]] = sub <8 x i16> [[TMP13]], [[TMP12]] -// CHECK: store volatile <8 x i16> [[SUB6]], ptr @us, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SUB7:%.*]] = sub <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[SUB7]], ptr @us, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SUB8:%.*]] = sub <4 x i32> [[TMP17]], [[TMP16]] -// CHECK: store volatile <4 x i32> [[SUB8]], ptr @si, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SUB9:%.*]] = sub <4 x i32> [[TMP19]], [[TMP18]] -// CHECK: store volatile <4 x i32> [[SUB9]], ptr @si, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SUB10:%.*]] = sub <4 x i32> [[TMP21]], [[TMP20]] -// CHECK: store volatile <4 x i32> [[SUB10]], ptr @ui, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SUB11:%.*]] = sub <4 x i32> [[TMP23]], [[TMP22]] -// CHECK: store volatile <4 x i32> [[SUB11]], ptr @ui, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SUB12:%.*]] = sub <2 x i64> [[TMP25]], [[TMP24]] -// CHECK: store volatile <2 x i64> [[SUB12]], ptr @sl, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SUB13:%.*]] = sub <2 x i64> [[TMP27]], [[TMP26]] -// CHECK: store volatile <2 x i64> [[SUB13]], ptr @sl, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SUB14:%.*]] = sub <2 x i64> [[TMP29]], [[TMP28]] -// CHECK: store volatile <2 x i64> [[SUB14]], ptr @ul, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SUB15:%.*]] = sub <2 x i64> [[TMP31]], [[TMP30]] -// CHECK: store volatile <2 x i64> [[SUB15]], ptr @ul, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[SUB16:%.*]] = fsub <2 x double> [[TMP33]], [[TMP32]] -// CHECK: store volatile <2 x double> [[SUB16]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_sub_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SUB:%.*]] = sub <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SUB1:%.*]] = sub <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SUB2:%.*]] = sub <16 x i8> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB2]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SUB3:%.*]] = sub <16 x i8> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <16 x i8> [[SUB3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SUB4:%.*]] = sub <8 x i16> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB4]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SUB5:%.*]] = sub <8 x i16> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB5]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SUB6:%.*]] = sub <8 x i16> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB6]], ptr @us, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SUB7:%.*]] = sub <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[SUB7]], ptr @us, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SUB8:%.*]] = sub <4 x i32> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB8]], ptr @si, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SUB9:%.*]] = sub <4 x i32> [[TMP19]], [[TMP18]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB9]], ptr @si, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SUB10:%.*]] = sub <4 x i32> [[TMP21]], [[TMP20]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB10]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SUB11:%.*]] = sub <4 x i32> [[TMP23]], [[TMP22]] +// CHECK-NEXT: store volatile <4 x i32> [[SUB11]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SUB12:%.*]] = sub <2 x i64> [[TMP25]], [[TMP24]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB12]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SUB13:%.*]] = sub <2 x i64> [[TMP27]], [[TMP26]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB13]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SUB14:%.*]] = sub <2 x i64> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB14]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SUB15:%.*]] = sub <2 x i64> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <2 x i64> [[SUB15]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[SUB16:%.*]] = fsub <2 x double> [[TMP33]], [[TMP32]] +// CHECK-NEXT: store volatile <2 x double> [[SUB16]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_sub_assign(void) { sc -= sc2; @@ -766,44 +800,47 @@ void test_sub_assign(void) { fd -= fd2; } -// CHECK-LABEL: define{{.*}} void @test_mul() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[MUL:%.*]] = mul <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[MUL]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[MUL1:%.*]] = mul <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[MUL1]], ptr @uc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[MUL2:%.*]] = mul <8 x i16> [[TMP4]], [[TMP5]] -// CHECK: store volatile <8 x i16> [[MUL2]], ptr @ss, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[MUL3:%.*]] = mul <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: store volatile <8 x i16> [[MUL3]], ptr @us, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[MUL4:%.*]] = mul <4 x i32> [[TMP8]], [[TMP9]] -// CHECK: store volatile <4 x i32> [[MUL4]], ptr @si, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[MUL5:%.*]] = mul <4 x i32> [[TMP10]], [[TMP11]] -// CHECK: store volatile <4 x i32> [[MUL5]], ptr @ui, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[MUL6:%.*]] = mul <2 x i64> [[TMP12]], [[TMP13]] -// CHECK: store volatile <2 x i64> [[MUL6]], ptr @sl, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[MUL7:%.*]] = mul <2 x i64> [[TMP14]], [[TMP15]] -// CHECK: store volatile <2 x i64> [[MUL7]], ptr @ul, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[MUL8:%.*]] = fmul <2 x double> [[TMP16]], [[TMP17]] -// CHECK: store volatile <2 x double> [[MUL8]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_mul( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[MUL]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[MUL1:%.*]] = mul <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[MUL1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[MUL2:%.*]] = mul <8 x i16> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <8 x i16> [[MUL2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[MUL3:%.*]] = mul <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <8 x i16> [[MUL3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[MUL4:%.*]] = mul <4 x i32> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <4 x i32> [[MUL4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[MUL5:%.*]] = mul <4 x i32> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <4 x i32> [[MUL5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[MUL6:%.*]] = mul <2 x i64> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <2 x i64> [[MUL6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[MUL7:%.*]] = mul <2 x i64> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <2 x i64> [[MUL7]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[MUL8:%.*]] = fmul <2 x double> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <2 x double> [[MUL8]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_mul(void) { sc = sc * sc2; @@ -821,44 +858,47 @@ void test_mul(void) { fd = fd * fd2; } -// CHECK-LABEL: define{{.*}} void @test_mul_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[MUL:%.*]] = mul <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[MUL]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[MUL1:%.*]] = mul <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[MUL1]], ptr @uc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[MUL2:%.*]] = mul <8 x i16> [[TMP5]], [[TMP4]] -// CHECK: store volatile <8 x i16> [[MUL2]], ptr @ss, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[MUL3:%.*]] = mul <8 x i16> [[TMP7]], [[TMP6]] -// CHECK: store volatile <8 x i16> [[MUL3]], ptr @us, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[MUL4:%.*]] = mul <4 x i32> [[TMP9]], [[TMP8]] -// CHECK: store volatile <4 x i32> [[MUL4]], ptr @si, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[MUL5:%.*]] = mul <4 x i32> [[TMP11]], [[TMP10]] -// CHECK: store volatile <4 x i32> [[MUL5]], ptr @ui, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[MUL6:%.*]] = mul <2 x i64> [[TMP13]], [[TMP12]] -// CHECK: store volatile <2 x i64> [[MUL6]], ptr @sl, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[MUL7:%.*]] = mul <2 x i64> [[TMP15]], [[TMP14]] -// CHECK: store volatile <2 x i64> [[MUL7]], ptr @ul, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[MUL8:%.*]] = fmul <2 x double> [[TMP17]], [[TMP16]] -// CHECK: store volatile <2 x double> [[MUL8]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_mul_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[MUL:%.*]] = mul <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[MUL]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[MUL1:%.*]] = mul <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[MUL1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[MUL2:%.*]] = mul <8 x i16> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <8 x i16> [[MUL2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[MUL3:%.*]] = mul <8 x i16> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <8 x i16> [[MUL3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[MUL4:%.*]] = mul <4 x i32> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <4 x i32> [[MUL4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[MUL5:%.*]] = mul <4 x i32> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <4 x i32> [[MUL5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[MUL6:%.*]] = mul <2 x i64> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <2 x i64> [[MUL6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[MUL7:%.*]] = mul <2 x i64> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <2 x i64> [[MUL7]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[MUL8:%.*]] = fmul <2 x double> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <2 x double> [[MUL8]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_mul_assign(void) { sc *= sc2; @@ -876,44 +916,47 @@ void test_mul_assign(void) { fd *= fd2; } -// CHECK-LABEL: define{{.*}} void @test_div() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[DIV:%.*]] = sdiv <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[DIV]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[DIV1:%.*]] = udiv <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[DIV1]], ptr @uc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[DIV2:%.*]] = sdiv <8 x i16> [[TMP4]], [[TMP5]] -// CHECK: store volatile <8 x i16> [[DIV2]], ptr @ss, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[DIV3:%.*]] = udiv <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: store volatile <8 x i16> [[DIV3]], ptr @us, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[DIV4:%.*]] = sdiv <4 x i32> [[TMP8]], [[TMP9]] -// CHECK: store volatile <4 x i32> [[DIV4]], ptr @si, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[DIV5:%.*]] = udiv <4 x i32> [[TMP10]], [[TMP11]] -// CHECK: store volatile <4 x i32> [[DIV5]], ptr @ui, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[DIV6:%.*]] = sdiv <2 x i64> [[TMP12]], [[TMP13]] -// CHECK: store volatile <2 x i64> [[DIV6]], ptr @sl, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[DIV7:%.*]] = udiv <2 x i64> [[TMP14]], [[TMP15]] -// CHECK: store volatile <2 x i64> [[DIV7]], ptr @ul, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[DIV8:%.*]] = fdiv <2 x double> [[TMP16]], [[TMP17]] -// CHECK: store volatile <2 x double> [[DIV8]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_div( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[DIV:%.*]] = sdiv <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[DIV]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[DIV1:%.*]] = udiv <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[DIV1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[DIV2:%.*]] = sdiv <8 x i16> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <8 x i16> [[DIV2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[DIV3:%.*]] = udiv <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <8 x i16> [[DIV3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[DIV4:%.*]] = sdiv <4 x i32> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <4 x i32> [[DIV4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[DIV5:%.*]] = udiv <4 x i32> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <4 x i32> [[DIV5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[DIV6:%.*]] = sdiv <2 x i64> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <2 x i64> [[DIV6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[DIV7:%.*]] = udiv <2 x i64> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <2 x i64> [[DIV7]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[DIV8:%.*]] = fdiv <2 x double> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <2 x double> [[DIV8]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_div(void) { sc = sc / sc2; @@ -931,44 +974,47 @@ void test_div(void) { fd = fd / fd2; } -// CHECK-LABEL: define{{.*}} void @test_div_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[DIV:%.*]] = sdiv <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[DIV]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[DIV1:%.*]] = udiv <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[DIV1]], ptr @uc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[DIV2:%.*]] = sdiv <8 x i16> [[TMP5]], [[TMP4]] -// CHECK: store volatile <8 x i16> [[DIV2]], ptr @ss, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[DIV3:%.*]] = udiv <8 x i16> [[TMP7]], [[TMP6]] -// CHECK: store volatile <8 x i16> [[DIV3]], ptr @us, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[DIV4:%.*]] = sdiv <4 x i32> [[TMP9]], [[TMP8]] -// CHECK: store volatile <4 x i32> [[DIV4]], ptr @si, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[DIV5:%.*]] = udiv <4 x i32> [[TMP11]], [[TMP10]] -// CHECK: store volatile <4 x i32> [[DIV5]], ptr @ui, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[DIV6:%.*]] = sdiv <2 x i64> [[TMP13]], [[TMP12]] -// CHECK: store volatile <2 x i64> [[DIV6]], ptr @sl, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[DIV7:%.*]] = udiv <2 x i64> [[TMP15]], [[TMP14]] -// CHECK: store volatile <2 x i64> [[DIV7]], ptr @ul, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[DIV8:%.*]] = fdiv <2 x double> [[TMP17]], [[TMP16]] -// CHECK: store volatile <2 x double> [[DIV8]], ptr @fd, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_div_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[DIV:%.*]] = sdiv <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[DIV]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[DIV1:%.*]] = udiv <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[DIV1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[DIV2:%.*]] = sdiv <8 x i16> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <8 x i16> [[DIV2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[DIV3:%.*]] = udiv <8 x i16> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <8 x i16> [[DIV3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[DIV4:%.*]] = sdiv <4 x i32> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <4 x i32> [[DIV4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[DIV5:%.*]] = udiv <4 x i32> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <4 x i32> [[DIV5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[DIV6:%.*]] = sdiv <2 x i64> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <2 x i64> [[DIV6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[DIV7:%.*]] = udiv <2 x i64> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <2 x i64> [[DIV7]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[DIV8:%.*]] = fdiv <2 x double> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <2 x double> [[DIV8]], ptr @fd, align 8 +// CHECK-NEXT: ret void +// void test_div_assign(void) { sc /= sc2; @@ -986,40 +1032,43 @@ void test_div_assign(void) { fd /= fd2; } -// CHECK-LABEL: define{{.*}} void @test_rem() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[REM:%.*]] = srem <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[REM]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[REM1:%.*]] = urem <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[REM1]], ptr @uc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[REM2:%.*]] = srem <8 x i16> [[TMP4]], [[TMP5]] -// CHECK: store volatile <8 x i16> [[REM2]], ptr @ss, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[REM3:%.*]] = urem <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: store volatile <8 x i16> [[REM3]], ptr @us, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[REM4:%.*]] = srem <4 x i32> [[TMP8]], [[TMP9]] -// CHECK: store volatile <4 x i32> [[REM4]], ptr @si, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[REM5:%.*]] = urem <4 x i32> [[TMP10]], [[TMP11]] -// CHECK: store volatile <4 x i32> [[REM5]], ptr @ui, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[REM6:%.*]] = srem <2 x i64> [[TMP12]], [[TMP13]] -// CHECK: store volatile <2 x i64> [[REM6]], ptr @sl, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[REM7:%.*]] = urem <2 x i64> [[TMP14]], [[TMP15]] -// CHECK: store volatile <2 x i64> [[REM7]], ptr @ul, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_rem( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[REM:%.*]] = srem <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[REM]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[REM1:%.*]] = urem <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[REM1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[REM2:%.*]] = srem <8 x i16> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <8 x i16> [[REM2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[REM3:%.*]] = urem <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <8 x i16> [[REM3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[REM4:%.*]] = srem <4 x i32> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <4 x i32> [[REM4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[REM5:%.*]] = urem <4 x i32> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <4 x i32> [[REM5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[REM6:%.*]] = srem <2 x i64> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <2 x i64> [[REM6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[REM7:%.*]] = urem <2 x i64> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <2 x i64> [[REM7]], ptr @ul, align 8 +// CHECK-NEXT: ret void +// void test_rem(void) { sc = sc % sc2; @@ -1035,40 +1084,43 @@ void test_rem(void) { ul = ul % ul2; } -// CHECK-LABEL: define{{.*}} void @test_rem_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[REM:%.*]] = srem <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[REM]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[REM1:%.*]] = urem <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[REM1]], ptr @uc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[REM2:%.*]] = srem <8 x i16> [[TMP5]], [[TMP4]] -// CHECK: store volatile <8 x i16> [[REM2]], ptr @ss, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[REM3:%.*]] = urem <8 x i16> [[TMP7]], [[TMP6]] -// CHECK: store volatile <8 x i16> [[REM3]], ptr @us, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[REM4:%.*]] = srem <4 x i32> [[TMP9]], [[TMP8]] -// CHECK: store volatile <4 x i32> [[REM4]], ptr @si, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[REM5:%.*]] = urem <4 x i32> [[TMP11]], [[TMP10]] -// CHECK: store volatile <4 x i32> [[REM5]], ptr @ui, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[REM6:%.*]] = srem <2 x i64> [[TMP13]], [[TMP12]] -// CHECK: store volatile <2 x i64> [[REM6]], ptr @sl, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[REM7:%.*]] = urem <2 x i64> [[TMP15]], [[TMP14]] -// CHECK: store volatile <2 x i64> [[REM7]], ptr @ul, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_rem_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[REM:%.*]] = srem <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[REM]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[REM1:%.*]] = urem <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[REM1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[REM2:%.*]] = srem <8 x i16> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <8 x i16> [[REM2]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[REM3:%.*]] = urem <8 x i16> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <8 x i16> [[REM3]], ptr @us, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[REM4:%.*]] = srem <4 x i32> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <4 x i32> [[REM4]], ptr @si, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[REM5:%.*]] = urem <4 x i32> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <4 x i32> [[REM5]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[REM6:%.*]] = srem <2 x i64> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <2 x i64> [[REM6]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[REM7:%.*]] = urem <2 x i64> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <2 x i64> [[REM7]], ptr @ul, align 8 +// CHECK-NEXT: ret void +// void test_rem_assign(void) { sc %= sc2; @@ -1084,44 +1136,47 @@ void test_rem_assign(void) { ul %= ul2; } -// CHECK-LABEL: define{{.*}} void @test_not() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[NEG:%.*]] = xor <16 x i8> [[TMP0]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[NEG]], ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[NEG1:%.*]] = xor <16 x i8> [[TMP1]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[NEG1]], ptr @uc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[NEG2:%.*]] = xor <16 x i8> [[TMP2]], splat (i8 -1) -// CHECK: store volatile <16 x i8> [[NEG2]], ptr @bc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[NEG3:%.*]] = xor <8 x i16> [[TMP3]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[NEG3]], ptr @ss, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[NEG4:%.*]] = xor <8 x i16> [[TMP4]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[NEG4]], ptr @us, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[NEG5:%.*]] = xor <8 x i16> [[TMP5]], splat (i16 -1) -// CHECK: store volatile <8 x i16> [[NEG5]], ptr @bs, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[NEG6:%.*]] = xor <4 x i32> [[TMP6]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[NEG6]], ptr @si, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[NEG7:%.*]] = xor <4 x i32> [[TMP7]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[NEG7]], ptr @ui, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[NEG8:%.*]] = xor <4 x i32> [[TMP8]], splat (i32 -1) -// CHECK: store volatile <4 x i32> [[NEG8]], ptr @bi, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[NEG9:%.*]] = xor <2 x i64> [[TMP9]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[NEG9]], ptr @sl, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[NEG10:%.*]] = xor <2 x i64> [[TMP10]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[NEG10]], ptr @ul, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[NEG11:%.*]] = xor <2 x i64> [[TMP11]], splat (i64 -1) -// CHECK: store volatile <2 x i64> [[NEG11]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_not( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[NOT:%.*]] = xor <16 x i8> [[TMP0]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[NOT]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[NOT1:%.*]] = xor <16 x i8> [[TMP1]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[NOT1]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[NOT2:%.*]] = xor <16 x i8> [[TMP2]], splat (i8 -1) +// CHECK-NEXT: store volatile <16 x i8> [[NOT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[NOT3:%.*]] = xor <8 x i16> [[TMP3]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[NOT3]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[NOT4:%.*]] = xor <8 x i16> [[TMP4]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[NOT4]], ptr @us, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[NOT5:%.*]] = xor <8 x i16> [[TMP5]], splat (i16 -1) +// CHECK-NEXT: store volatile <8 x i16> [[NOT5]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[NOT6:%.*]] = xor <4 x i32> [[TMP6]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[NOT6]], ptr @si, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[NOT7:%.*]] = xor <4 x i32> [[TMP7]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[NOT7]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[NOT8:%.*]] = xor <4 x i32> [[TMP8]], splat (i32 -1) +// CHECK-NEXT: store volatile <4 x i32> [[NOT8]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[NOT9:%.*]] = xor <2 x i64> [[TMP9]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[NOT9]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[NOT10:%.*]] = xor <2 x i64> [[TMP10]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[NOT10]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[NOT11:%.*]] = xor <2 x i64> [[TMP11]], splat (i64 -1) +// CHECK-NEXT: store volatile <2 x i64> [[NOT11]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_not(void) { sc = ~sc2; @@ -1141,120 +1196,123 @@ void test_not(void) { bl = ~bl2; } -// CHECK-LABEL: define{{.*}} void @test_and() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[AND:%.*]] = and <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[AND]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[AND1:%.*]] = and <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[AND1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[AND2:%.*]] = and <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: store volatile <16 x i8> [[AND2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[AND3:%.*]] = and <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[AND3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[AND4:%.*]] = and <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[AND4]], ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[AND5:%.*]] = and <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: store volatile <16 x i8> [[AND5]], ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[AND6:%.*]] = and <16 x i8> [[TMP12]], [[TMP13]] -// CHECK: store volatile <16 x i8> [[AND6]], ptr @bc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[AND7:%.*]] = and <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[AND7]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[AND8:%.*]] = and <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[AND8]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[AND9:%.*]] = and <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: store volatile <8 x i16> [[AND9]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[AND10:%.*]] = and <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[AND10]], ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[AND11:%.*]] = and <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[AND11]], ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[AND12:%.*]] = and <8 x i16> [[TMP24]], [[TMP25]] -// CHECK: store volatile <8 x i16> [[AND12]], ptr @us, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[AND13:%.*]] = and <8 x i16> [[TMP26]], [[TMP27]] -// CHECK: store volatile <8 x i16> [[AND13]], ptr @bs, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[AND14:%.*]] = and <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[AND14]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[AND15:%.*]] = and <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[AND15]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[AND16:%.*]] = and <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: store volatile <4 x i32> [[AND16]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[AND17:%.*]] = and <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[AND17]], ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[AND18:%.*]] = and <4 x i32> [[TMP36]], [[TMP37]] -// CHECK: store volatile <4 x i32> [[AND18]], ptr @ui, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[AND19:%.*]] = and <4 x i32> [[TMP38]], [[TMP39]] -// CHECK: store volatile <4 x i32> [[AND19]], ptr @ui, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[AND20:%.*]] = and <4 x i32> [[TMP40]], [[TMP41]] -// CHECK: store volatile <4 x i32> [[AND20]], ptr @bi, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[AND21:%.*]] = and <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[AND21]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[AND22:%.*]] = and <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[AND22]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[AND23:%.*]] = and <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: store volatile <2 x i64> [[AND23]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[AND24:%.*]] = and <2 x i64> [[TMP48]], [[TMP49]] -// CHECK: store volatile <2 x i64> [[AND24]], ptr @ul, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[AND25:%.*]] = and <2 x i64> [[TMP50]], [[TMP51]] -// CHECK: store volatile <2 x i64> [[AND25]], ptr @ul, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[AND26:%.*]] = and <2 x i64> [[TMP52]], [[TMP53]] -// CHECK: store volatile <2 x i64> [[AND26]], ptr @ul, align 8 -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[AND27:%.*]] = and <2 x i64> [[TMP54]], [[TMP55]] -// CHECK: store volatile <2 x i64> [[AND27]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_and( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[AND:%.*]] = and <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[AND]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[AND1:%.*]] = and <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[AND1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[AND2:%.*]] = and <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <16 x i8> [[AND2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[AND3:%.*]] = and <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[AND3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[AND4:%.*]] = and <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[AND4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[AND5:%.*]] = and <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <16 x i8> [[AND5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[AND6:%.*]] = and <16 x i8> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <16 x i8> [[AND6]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[AND7:%.*]] = and <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[AND7]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[AND8:%.*]] = and <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[AND8]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[AND9:%.*]] = and <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: store volatile <8 x i16> [[AND9]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[AND10:%.*]] = and <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[AND10]], ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[AND11:%.*]] = and <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[AND11]], ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[AND12:%.*]] = and <8 x i16> [[TMP24]], [[TMP25]] +// CHECK-NEXT: store volatile <8 x i16> [[AND12]], ptr @us, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[AND13:%.*]] = and <8 x i16> [[TMP26]], [[TMP27]] +// CHECK-NEXT: store volatile <8 x i16> [[AND13]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[AND14:%.*]] = and <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[AND14]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[AND15:%.*]] = and <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[AND15]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[AND16:%.*]] = and <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: store volatile <4 x i32> [[AND16]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[AND17:%.*]] = and <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[AND17]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[AND18:%.*]] = and <4 x i32> [[TMP36]], [[TMP37]] +// CHECK-NEXT: store volatile <4 x i32> [[AND18]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[AND19:%.*]] = and <4 x i32> [[TMP38]], [[TMP39]] +// CHECK-NEXT: store volatile <4 x i32> [[AND19]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[AND20:%.*]] = and <4 x i32> [[TMP40]], [[TMP41]] +// CHECK-NEXT: store volatile <4 x i32> [[AND20]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[AND21:%.*]] = and <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[AND21]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[AND22:%.*]] = and <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[AND22]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[AND23:%.*]] = and <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: store volatile <2 x i64> [[AND23]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[AND24:%.*]] = and <2 x i64> [[TMP48]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x i64> [[AND24]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[AND25:%.*]] = and <2 x i64> [[TMP50]], [[TMP51]] +// CHECK-NEXT: store volatile <2 x i64> [[AND25]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[AND26:%.*]] = and <2 x i64> [[TMP52]], [[TMP53]] +// CHECK-NEXT: store volatile <2 x i64> [[AND26]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[AND27:%.*]] = and <2 x i64> [[TMP54]], [[TMP55]] +// CHECK-NEXT: store volatile <2 x i64> [[AND27]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_and(void) { sc = sc & sc2; @@ -1290,88 +1348,91 @@ void test_and(void) { bl = bl & bl2; } -// CHECK-LABEL: define{{.*}} void @test_and_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[AND:%.*]] = and <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[AND]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[AND1:%.*]] = and <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[AND1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[AND2:%.*]] = and <16 x i8> [[TMP5]], [[TMP4]] -// CHECK: store volatile <16 x i8> [[AND2]], ptr @uc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[AND3:%.*]] = and <16 x i8> [[TMP7]], [[TMP6]] -// CHECK: store volatile <16 x i8> [[AND3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[AND4:%.*]] = and <16 x i8> [[TMP9]], [[TMP8]] -// CHECK: store volatile <16 x i8> [[AND4]], ptr @bc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[AND5:%.*]] = and <8 x i16> [[TMP11]], [[TMP10]] -// CHECK: store volatile <8 x i16> [[AND5]], ptr @ss, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[AND6:%.*]] = and <8 x i16> [[TMP13]], [[TMP12]] -// CHECK: store volatile <8 x i16> [[AND6]], ptr @ss, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[AND7:%.*]] = and <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[AND7]], ptr @us, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[AND8:%.*]] = and <8 x i16> [[TMP17]], [[TMP16]] -// CHECK: store volatile <8 x i16> [[AND8]], ptr @us, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[AND9:%.*]] = and <8 x i16> [[TMP19]], [[TMP18]] -// CHECK: store volatile <8 x i16> [[AND9]], ptr @bs, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[AND10:%.*]] = and <4 x i32> [[TMP21]], [[TMP20]] -// CHECK: store volatile <4 x i32> [[AND10]], ptr @si, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[AND11:%.*]] = and <4 x i32> [[TMP23]], [[TMP22]] -// CHECK: store volatile <4 x i32> [[AND11]], ptr @si, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[AND12:%.*]] = and <4 x i32> [[TMP25]], [[TMP24]] -// CHECK: store volatile <4 x i32> [[AND12]], ptr @ui, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[AND13:%.*]] = and <4 x i32> [[TMP27]], [[TMP26]] -// CHECK: store volatile <4 x i32> [[AND13]], ptr @ui, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[AND14:%.*]] = and <4 x i32> [[TMP29]], [[TMP28]] -// CHECK: store volatile <4 x i32> [[AND14]], ptr @bi, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[AND15:%.*]] = and <2 x i64> [[TMP31]], [[TMP30]] -// CHECK: store volatile <2 x i64> [[AND15]], ptr @sl, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[AND16:%.*]] = and <2 x i64> [[TMP33]], [[TMP32]] -// CHECK: store volatile <2 x i64> [[AND16]], ptr @sl, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[AND17:%.*]] = and <2 x i64> [[TMP35]], [[TMP34]] -// CHECK: store volatile <2 x i64> [[AND17]], ptr @ul, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[AND18:%.*]] = and <2 x i64> [[TMP37]], [[TMP36]] -// CHECK: store volatile <2 x i64> [[AND18]], ptr @ul, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[AND19:%.*]] = and <2 x i64> [[TMP39]], [[TMP38]] -// CHECK: store volatile <2 x i64> [[AND19]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_and_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[AND:%.*]] = and <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[AND]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[AND1:%.*]] = and <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[AND1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[AND2:%.*]] = and <16 x i8> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <16 x i8> [[AND2]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[AND3:%.*]] = and <16 x i8> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <16 x i8> [[AND3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[AND4:%.*]] = and <16 x i8> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <16 x i8> [[AND4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[AND5:%.*]] = and <8 x i16> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <8 x i16> [[AND5]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[AND6:%.*]] = and <8 x i16> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <8 x i16> [[AND6]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[AND7:%.*]] = and <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[AND7]], ptr @us, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[AND8:%.*]] = and <8 x i16> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <8 x i16> [[AND8]], ptr @us, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[AND9:%.*]] = and <8 x i16> [[TMP19]], [[TMP18]] +// CHECK-NEXT: store volatile <8 x i16> [[AND9]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[AND10:%.*]] = and <4 x i32> [[TMP21]], [[TMP20]] +// CHECK-NEXT: store volatile <4 x i32> [[AND10]], ptr @si, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[AND11:%.*]] = and <4 x i32> [[TMP23]], [[TMP22]] +// CHECK-NEXT: store volatile <4 x i32> [[AND11]], ptr @si, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[AND12:%.*]] = and <4 x i32> [[TMP25]], [[TMP24]] +// CHECK-NEXT: store volatile <4 x i32> [[AND12]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[AND13:%.*]] = and <4 x i32> [[TMP27]], [[TMP26]] +// CHECK-NEXT: store volatile <4 x i32> [[AND13]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[AND14:%.*]] = and <4 x i32> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <4 x i32> [[AND14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[AND15:%.*]] = and <2 x i64> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <2 x i64> [[AND15]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[AND16:%.*]] = and <2 x i64> [[TMP33]], [[TMP32]] +// CHECK-NEXT: store volatile <2 x i64> [[AND16]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[AND17:%.*]] = and <2 x i64> [[TMP35]], [[TMP34]] +// CHECK-NEXT: store volatile <2 x i64> [[AND17]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[AND18:%.*]] = and <2 x i64> [[TMP37]], [[TMP36]] +// CHECK-NEXT: store volatile <2 x i64> [[AND18]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[AND19:%.*]] = and <2 x i64> [[TMP39]], [[TMP38]] +// CHECK-NEXT: store volatile <2 x i64> [[AND19]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_and_assign(void) { sc &= sc2; @@ -1399,120 +1460,123 @@ void test_and_assign(void) { bl &= bl2; } -// CHECK-LABEL: define{{.*}} void @test_or() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[OR:%.*]] = or <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[OR]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[OR1:%.*]] = or <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[OR1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[OR2:%.*]] = or <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: store volatile <16 x i8> [[OR2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[OR3:%.*]] = or <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[OR3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[OR4:%.*]] = or <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[OR4]], ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[OR5:%.*]] = or <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: store volatile <16 x i8> [[OR5]], ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[OR6:%.*]] = or <16 x i8> [[TMP12]], [[TMP13]] -// CHECK: store volatile <16 x i8> [[OR6]], ptr @bc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[OR7:%.*]] = or <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[OR7]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[OR8:%.*]] = or <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[OR8]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[OR9:%.*]] = or <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: store volatile <8 x i16> [[OR9]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[OR10:%.*]] = or <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[OR10]], ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[OR11:%.*]] = or <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[OR11]], ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[OR12:%.*]] = or <8 x i16> [[TMP24]], [[TMP25]] -// CHECK: store volatile <8 x i16> [[OR12]], ptr @us, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[OR13:%.*]] = or <8 x i16> [[TMP26]], [[TMP27]] -// CHECK: store volatile <8 x i16> [[OR13]], ptr @bs, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[OR14:%.*]] = or <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[OR14]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[OR15:%.*]] = or <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[OR15]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[OR16:%.*]] = or <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: store volatile <4 x i32> [[OR16]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[OR17:%.*]] = or <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[OR17]], ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[OR18:%.*]] = or <4 x i32> [[TMP36]], [[TMP37]] -// CHECK: store volatile <4 x i32> [[OR18]], ptr @ui, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[OR19:%.*]] = or <4 x i32> [[TMP38]], [[TMP39]] -// CHECK: store volatile <4 x i32> [[OR19]], ptr @ui, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[OR20:%.*]] = or <4 x i32> [[TMP40]], [[TMP41]] -// CHECK: store volatile <4 x i32> [[OR20]], ptr @bi, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[OR21:%.*]] = or <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[OR21]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[OR22:%.*]] = or <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[OR22]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[OR23:%.*]] = or <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: store volatile <2 x i64> [[OR23]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[OR24:%.*]] = or <2 x i64> [[TMP48]], [[TMP49]] -// CHECK: store volatile <2 x i64> [[OR24]], ptr @ul, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[OR25:%.*]] = or <2 x i64> [[TMP50]], [[TMP51]] -// CHECK: store volatile <2 x i64> [[OR25]], ptr @ul, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[OR26:%.*]] = or <2 x i64> [[TMP52]], [[TMP53]] -// CHECK: store volatile <2 x i64> [[OR26]], ptr @ul, align 8 -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[OR27:%.*]] = or <2 x i64> [[TMP54]], [[TMP55]] -// CHECK: store volatile <2 x i64> [[OR27]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_or( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[OR:%.*]] = or <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[OR]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[OR1:%.*]] = or <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[OR1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[OR2:%.*]] = or <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <16 x i8> [[OR2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[OR3:%.*]] = or <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[OR3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[OR4:%.*]] = or <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[OR4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[OR5:%.*]] = or <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <16 x i8> [[OR5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[OR6:%.*]] = or <16 x i8> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <16 x i8> [[OR6]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[OR7:%.*]] = or <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[OR7]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[OR8:%.*]] = or <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[OR8]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[OR9:%.*]] = or <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: store volatile <8 x i16> [[OR9]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[OR10:%.*]] = or <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[OR10]], ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[OR11:%.*]] = or <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[OR11]], ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[OR12:%.*]] = or <8 x i16> [[TMP24]], [[TMP25]] +// CHECK-NEXT: store volatile <8 x i16> [[OR12]], ptr @us, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[OR13:%.*]] = or <8 x i16> [[TMP26]], [[TMP27]] +// CHECK-NEXT: store volatile <8 x i16> [[OR13]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[OR14:%.*]] = or <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[OR14]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[OR15:%.*]] = or <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[OR15]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[OR16:%.*]] = or <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: store volatile <4 x i32> [[OR16]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[OR17:%.*]] = or <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[OR17]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[OR18:%.*]] = or <4 x i32> [[TMP36]], [[TMP37]] +// CHECK-NEXT: store volatile <4 x i32> [[OR18]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[OR19:%.*]] = or <4 x i32> [[TMP38]], [[TMP39]] +// CHECK-NEXT: store volatile <4 x i32> [[OR19]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[OR20:%.*]] = or <4 x i32> [[TMP40]], [[TMP41]] +// CHECK-NEXT: store volatile <4 x i32> [[OR20]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[OR21:%.*]] = or <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[OR21]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[OR22:%.*]] = or <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[OR22]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[OR23:%.*]] = or <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: store volatile <2 x i64> [[OR23]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[OR24:%.*]] = or <2 x i64> [[TMP48]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x i64> [[OR24]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[OR25:%.*]] = or <2 x i64> [[TMP50]], [[TMP51]] +// CHECK-NEXT: store volatile <2 x i64> [[OR25]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[OR26:%.*]] = or <2 x i64> [[TMP52]], [[TMP53]] +// CHECK-NEXT: store volatile <2 x i64> [[OR26]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[OR27:%.*]] = or <2 x i64> [[TMP54]], [[TMP55]] +// CHECK-NEXT: store volatile <2 x i64> [[OR27]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_or(void) { sc = sc | sc2; @@ -1548,88 +1612,91 @@ void test_or(void) { bl = bl | bl2; } -// CHECK-LABEL: define{{.*}} void @test_or_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[OR:%.*]] = or <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[OR]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[OR1:%.*]] = or <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[OR1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[OR2:%.*]] = or <16 x i8> [[TMP5]], [[TMP4]] -// CHECK: store volatile <16 x i8> [[OR2]], ptr @uc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[OR3:%.*]] = or <16 x i8> [[TMP7]], [[TMP6]] -// CHECK: store volatile <16 x i8> [[OR3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[OR4:%.*]] = or <16 x i8> [[TMP9]], [[TMP8]] -// CHECK: store volatile <16 x i8> [[OR4]], ptr @bc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[OR5:%.*]] = or <8 x i16> [[TMP11]], [[TMP10]] -// CHECK: store volatile <8 x i16> [[OR5]], ptr @ss, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[OR6:%.*]] = or <8 x i16> [[TMP13]], [[TMP12]] -// CHECK: store volatile <8 x i16> [[OR6]], ptr @ss, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[OR7:%.*]] = or <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[OR7]], ptr @us, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[OR8:%.*]] = or <8 x i16> [[TMP17]], [[TMP16]] -// CHECK: store volatile <8 x i16> [[OR8]], ptr @us, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[OR9:%.*]] = or <8 x i16> [[TMP19]], [[TMP18]] -// CHECK: store volatile <8 x i16> [[OR9]], ptr @bs, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[OR10:%.*]] = or <4 x i32> [[TMP21]], [[TMP20]] -// CHECK: store volatile <4 x i32> [[OR10]], ptr @si, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[OR11:%.*]] = or <4 x i32> [[TMP23]], [[TMP22]] -// CHECK: store volatile <4 x i32> [[OR11]], ptr @si, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[OR12:%.*]] = or <4 x i32> [[TMP25]], [[TMP24]] -// CHECK: store volatile <4 x i32> [[OR12]], ptr @ui, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[OR13:%.*]] = or <4 x i32> [[TMP27]], [[TMP26]] -// CHECK: store volatile <4 x i32> [[OR13]], ptr @ui, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[OR14:%.*]] = or <4 x i32> [[TMP29]], [[TMP28]] -// CHECK: store volatile <4 x i32> [[OR14]], ptr @bi, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[OR15:%.*]] = or <2 x i64> [[TMP31]], [[TMP30]] -// CHECK: store volatile <2 x i64> [[OR15]], ptr @sl, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[OR16:%.*]] = or <2 x i64> [[TMP33]], [[TMP32]] -// CHECK: store volatile <2 x i64> [[OR16]], ptr @sl, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[OR17:%.*]] = or <2 x i64> [[TMP35]], [[TMP34]] -// CHECK: store volatile <2 x i64> [[OR17]], ptr @ul, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[OR18:%.*]] = or <2 x i64> [[TMP37]], [[TMP36]] -// CHECK: store volatile <2 x i64> [[OR18]], ptr @ul, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[OR19:%.*]] = or <2 x i64> [[TMP39]], [[TMP38]] -// CHECK: store volatile <2 x i64> [[OR19]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_or_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[OR:%.*]] = or <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[OR]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[OR1:%.*]] = or <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[OR1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[OR2:%.*]] = or <16 x i8> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <16 x i8> [[OR2]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[OR3:%.*]] = or <16 x i8> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <16 x i8> [[OR3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[OR4:%.*]] = or <16 x i8> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <16 x i8> [[OR4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[OR5:%.*]] = or <8 x i16> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <8 x i16> [[OR5]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[OR6:%.*]] = or <8 x i16> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <8 x i16> [[OR6]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[OR7:%.*]] = or <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[OR7]], ptr @us, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[OR8:%.*]] = or <8 x i16> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <8 x i16> [[OR8]], ptr @us, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[OR9:%.*]] = or <8 x i16> [[TMP19]], [[TMP18]] +// CHECK-NEXT: store volatile <8 x i16> [[OR9]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[OR10:%.*]] = or <4 x i32> [[TMP21]], [[TMP20]] +// CHECK-NEXT: store volatile <4 x i32> [[OR10]], ptr @si, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[OR11:%.*]] = or <4 x i32> [[TMP23]], [[TMP22]] +// CHECK-NEXT: store volatile <4 x i32> [[OR11]], ptr @si, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[OR12:%.*]] = or <4 x i32> [[TMP25]], [[TMP24]] +// CHECK-NEXT: store volatile <4 x i32> [[OR12]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[OR13:%.*]] = or <4 x i32> [[TMP27]], [[TMP26]] +// CHECK-NEXT: store volatile <4 x i32> [[OR13]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[OR14:%.*]] = or <4 x i32> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <4 x i32> [[OR14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[OR15:%.*]] = or <2 x i64> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <2 x i64> [[OR15]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[OR16:%.*]] = or <2 x i64> [[TMP33]], [[TMP32]] +// CHECK-NEXT: store volatile <2 x i64> [[OR16]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[OR17:%.*]] = or <2 x i64> [[TMP35]], [[TMP34]] +// CHECK-NEXT: store volatile <2 x i64> [[OR17]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[OR18:%.*]] = or <2 x i64> [[TMP37]], [[TMP36]] +// CHECK-NEXT: store volatile <2 x i64> [[OR18]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[OR19:%.*]] = or <2 x i64> [[TMP39]], [[TMP38]] +// CHECK-NEXT: store volatile <2 x i64> [[OR19]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_or_assign(void) { sc |= sc2; @@ -1657,120 +1724,123 @@ void test_or_assign(void) { bl |= bl2; } -// CHECK-LABEL: define{{.*}} void @test_xor() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[XOR:%.*]] = xor <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[XOR]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[XOR1:%.*]] = xor <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[XOR1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[XOR2:%.*]] = xor <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: store volatile <16 x i8> [[XOR2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[XOR3:%.*]] = xor <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[XOR3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[XOR4:%.*]] = xor <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[XOR4]], ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[XOR5:%.*]] = xor <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: store volatile <16 x i8> [[XOR5]], ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[XOR6:%.*]] = xor <16 x i8> [[TMP12]], [[TMP13]] -// CHECK: store volatile <16 x i8> [[XOR6]], ptr @bc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[XOR7:%.*]] = xor <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[XOR7]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[XOR8:%.*]] = xor <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[XOR8]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[XOR9:%.*]] = xor <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: store volatile <8 x i16> [[XOR9]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[XOR10:%.*]] = xor <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[XOR10]], ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[XOR11:%.*]] = xor <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[XOR11]], ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[XOR12:%.*]] = xor <8 x i16> [[TMP24]], [[TMP25]] -// CHECK: store volatile <8 x i16> [[XOR12]], ptr @us, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[XOR13:%.*]] = xor <8 x i16> [[TMP26]], [[TMP27]] -// CHECK: store volatile <8 x i16> [[XOR13]], ptr @bs, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[XOR14:%.*]] = xor <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[XOR14]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[XOR15:%.*]] = xor <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[XOR15]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[XOR16:%.*]] = xor <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: store volatile <4 x i32> [[XOR16]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[XOR17:%.*]] = xor <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[XOR17]], ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[XOR18:%.*]] = xor <4 x i32> [[TMP36]], [[TMP37]] -// CHECK: store volatile <4 x i32> [[XOR18]], ptr @ui, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[XOR19:%.*]] = xor <4 x i32> [[TMP38]], [[TMP39]] -// CHECK: store volatile <4 x i32> [[XOR19]], ptr @ui, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[XOR20:%.*]] = xor <4 x i32> [[TMP40]], [[TMP41]] -// CHECK: store volatile <4 x i32> [[XOR20]], ptr @bi, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[XOR21:%.*]] = xor <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[XOR21]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[XOR22:%.*]] = xor <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[XOR22]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[XOR23:%.*]] = xor <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: store volatile <2 x i64> [[XOR23]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[XOR24:%.*]] = xor <2 x i64> [[TMP48]], [[TMP49]] -// CHECK: store volatile <2 x i64> [[XOR24]], ptr @ul, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[XOR25:%.*]] = xor <2 x i64> [[TMP50]], [[TMP51]] -// CHECK: store volatile <2 x i64> [[XOR25]], ptr @ul, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[XOR26:%.*]] = xor <2 x i64> [[TMP52]], [[TMP53]] -// CHECK: store volatile <2 x i64> [[XOR26]], ptr @ul, align 8 -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[XOR27:%.*]] = xor <2 x i64> [[TMP54]], [[TMP55]] -// CHECK: store volatile <2 x i64> [[XOR27]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_xor( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[XOR:%.*]] = xor <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[XOR1:%.*]] = xor <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[XOR2:%.*]] = xor <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[XOR3:%.*]] = xor <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[XOR4:%.*]] = xor <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[XOR5:%.*]] = xor <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[XOR6:%.*]] = xor <16 x i8> [[TMP12]], [[TMP13]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR6]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[XOR7:%.*]] = xor <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR7]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[XOR8:%.*]] = xor <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR8]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[XOR9:%.*]] = xor <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR9]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[XOR10:%.*]] = xor <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR10]], ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[XOR11:%.*]] = xor <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR11]], ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[XOR12:%.*]] = xor <8 x i16> [[TMP24]], [[TMP25]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR12]], ptr @us, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[XOR13:%.*]] = xor <8 x i16> [[TMP26]], [[TMP27]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR13]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[XOR14:%.*]] = xor <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR14]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[XOR15:%.*]] = xor <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR15]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[XOR16:%.*]] = xor <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR16]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[XOR17:%.*]] = xor <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR17]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[XOR18:%.*]] = xor <4 x i32> [[TMP36]], [[TMP37]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR18]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[XOR19:%.*]] = xor <4 x i32> [[TMP38]], [[TMP39]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR19]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[XOR20:%.*]] = xor <4 x i32> [[TMP40]], [[TMP41]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR20]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[XOR21:%.*]] = xor <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR21]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[XOR22:%.*]] = xor <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR22]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[XOR23:%.*]] = xor <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR23]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[XOR24:%.*]] = xor <2 x i64> [[TMP48]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR24]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[XOR25:%.*]] = xor <2 x i64> [[TMP50]], [[TMP51]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR25]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[XOR26:%.*]] = xor <2 x i64> [[TMP52]], [[TMP53]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR26]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[XOR27:%.*]] = xor <2 x i64> [[TMP54]], [[TMP55]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR27]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_xor(void) { sc = sc ^ sc2; @@ -1806,88 +1876,91 @@ void test_xor(void) { bl = bl ^ bl2; } -// CHECK-LABEL: define{{.*}} void @test_xor_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[XOR:%.*]] = xor <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[XOR]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[XOR1:%.*]] = xor <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[XOR1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[XOR2:%.*]] = xor <16 x i8> [[TMP5]], [[TMP4]] -// CHECK: store volatile <16 x i8> [[XOR2]], ptr @uc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[XOR3:%.*]] = xor <16 x i8> [[TMP7]], [[TMP6]] -// CHECK: store volatile <16 x i8> [[XOR3]], ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[XOR4:%.*]] = xor <16 x i8> [[TMP9]], [[TMP8]] -// CHECK: store volatile <16 x i8> [[XOR4]], ptr @bc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[XOR5:%.*]] = xor <8 x i16> [[TMP11]], [[TMP10]] -// CHECK: store volatile <8 x i16> [[XOR5]], ptr @ss, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[XOR6:%.*]] = xor <8 x i16> [[TMP13]], [[TMP12]] -// CHECK: store volatile <8 x i16> [[XOR6]], ptr @ss, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[XOR7:%.*]] = xor <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[XOR7]], ptr @us, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[XOR8:%.*]] = xor <8 x i16> [[TMP17]], [[TMP16]] -// CHECK: store volatile <8 x i16> [[XOR8]], ptr @us, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[XOR9:%.*]] = xor <8 x i16> [[TMP19]], [[TMP18]] -// CHECK: store volatile <8 x i16> [[XOR9]], ptr @bs, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[XOR10:%.*]] = xor <4 x i32> [[TMP21]], [[TMP20]] -// CHECK: store volatile <4 x i32> [[XOR10]], ptr @si, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[XOR11:%.*]] = xor <4 x i32> [[TMP23]], [[TMP22]] -// CHECK: store volatile <4 x i32> [[XOR11]], ptr @si, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[XOR12:%.*]] = xor <4 x i32> [[TMP25]], [[TMP24]] -// CHECK: store volatile <4 x i32> [[XOR12]], ptr @ui, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[XOR13:%.*]] = xor <4 x i32> [[TMP27]], [[TMP26]] -// CHECK: store volatile <4 x i32> [[XOR13]], ptr @ui, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[XOR14:%.*]] = xor <4 x i32> [[TMP29]], [[TMP28]] -// CHECK: store volatile <4 x i32> [[XOR14]], ptr @bi, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[XOR15:%.*]] = xor <2 x i64> [[TMP31]], [[TMP30]] -// CHECK: store volatile <2 x i64> [[XOR15]], ptr @sl, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[XOR16:%.*]] = xor <2 x i64> [[TMP33]], [[TMP32]] -// CHECK: store volatile <2 x i64> [[XOR16]], ptr @sl, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[XOR17:%.*]] = xor <2 x i64> [[TMP35]], [[TMP34]] -// CHECK: store volatile <2 x i64> [[XOR17]], ptr @ul, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[XOR18:%.*]] = xor <2 x i64> [[TMP37]], [[TMP36]] -// CHECK: store volatile <2 x i64> [[XOR18]], ptr @ul, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[XOR19:%.*]] = xor <2 x i64> [[TMP39]], [[TMP38]] -// CHECK: store volatile <2 x i64> [[XOR19]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_xor_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[XOR:%.*]] = xor <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[XOR1:%.*]] = xor <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[XOR2:%.*]] = xor <16 x i8> [[TMP5]], [[TMP4]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR2]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[XOR3:%.*]] = xor <16 x i8> [[TMP7]], [[TMP6]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR3]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[XOR4:%.*]] = xor <16 x i8> [[TMP9]], [[TMP8]] +// CHECK-NEXT: store volatile <16 x i8> [[XOR4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[XOR5:%.*]] = xor <8 x i16> [[TMP11]], [[TMP10]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR5]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[XOR6:%.*]] = xor <8 x i16> [[TMP13]], [[TMP12]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR6]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[XOR7:%.*]] = xor <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR7]], ptr @us, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[XOR8:%.*]] = xor <8 x i16> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR8]], ptr @us, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[XOR9:%.*]] = xor <8 x i16> [[TMP19]], [[TMP18]] +// CHECK-NEXT: store volatile <8 x i16> [[XOR9]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[XOR10:%.*]] = xor <4 x i32> [[TMP21]], [[TMP20]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR10]], ptr @si, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[XOR11:%.*]] = xor <4 x i32> [[TMP23]], [[TMP22]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR11]], ptr @si, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[XOR12:%.*]] = xor <4 x i32> [[TMP25]], [[TMP24]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR12]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[XOR13:%.*]] = xor <4 x i32> [[TMP27]], [[TMP26]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR13]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[XOR14:%.*]] = xor <4 x i32> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <4 x i32> [[XOR14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[XOR15:%.*]] = xor <2 x i64> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR15]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[XOR16:%.*]] = xor <2 x i64> [[TMP33]], [[TMP32]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR16]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[XOR17:%.*]] = xor <2 x i64> [[TMP35]], [[TMP34]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR17]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[XOR18:%.*]] = xor <2 x i64> [[TMP37]], [[TMP36]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR18]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[XOR19:%.*]] = xor <2 x i64> [[TMP39]], [[TMP38]] +// CHECK-NEXT: store volatile <2 x i64> [[XOR19]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_xor_assign(void) { sc ^= sc2; @@ -1915,150 +1988,153 @@ void test_xor_assign(void) { bl ^= bl2; } -// CHECK-LABEL: define{{.*}} void @test_sl() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SHL:%.*]] = shl <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[SHL]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[SHL1:%.*]] = shl <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[SHL1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP5]], i64 0 -// CHECK: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLAT:%.*]]insert, <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> -// CHECK: [[SHL2:%.*]] = shl <16 x i8> [[TMP4]], [[SH_PROM]] -// CHECK: store volatile <16 x i8> [[SHL2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHL3:%.*]] = shl <16 x i8> [[TMP6]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHL3]], ptr @sc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SHL4:%.*]] = shl <16 x i8> [[TMP7]], [[TMP8]] -// CHECK: store volatile <16 x i8> [[SHL4]], ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[SHL5:%.*]] = shl <16 x i8> [[TMP9]], [[TMP10]] -// CHECK: store volatile <16 x i8> [[SHL5]], ptr @uc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP12]], i64 0 -// CHECK: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> -// CHECK: [[SHL9:%.*]] = shl <16 x i8> [[TMP11]], [[SH_PROM8]] -// CHECK: store volatile <16 x i8> [[SHL9]], ptr @uc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHL10:%.*]] = shl <16 x i8> [[TMP13]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHL10]], ptr @uc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SHL11:%.*]] = shl <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[SHL11]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[SHL12:%.*]] = shl <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[SHL12]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP19:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP19]], i64 0 -// CHECK: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> -// CHECK: [[SHL16:%.*]] = shl <8 x i16> [[TMP18]], [[SH_PROM15]] -// CHECK: store volatile <8 x i16> [[SHL16]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHL17:%.*]] = shl <8 x i16> [[TMP20]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHL17]], ptr @ss, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SHL18:%.*]] = shl <8 x i16> [[TMP21]], [[TMP22]] -// CHECK: store volatile <8 x i16> [[SHL18]], ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[SHL19:%.*]] = shl <8 x i16> [[TMP23]], [[TMP24]] -// CHECK: store volatile <8 x i16> [[SHL19]], ptr @us, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP26:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP26]], i64 0 -// CHECK: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> -// CHECK: [[SHL23:%.*]] = shl <8 x i16> [[TMP25]], [[SH_PROM22]] -// CHECK: store volatile <8 x i16> [[SHL23]], ptr @us, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHL24:%.*]] = shl <8 x i16> [[TMP27]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHL24]], ptr @us, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SHL25:%.*]] = shl <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[SHL25]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[SHL26:%.*]] = shl <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[SHL26]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP33:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP33]], i64 0 -// CHECK: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[SHL29:%.*]] = shl <4 x i32> [[TMP32]], [[SPLAT_SPLAT28]] -// CHECK: store volatile <4 x i32> [[SHL29]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHL30:%.*]] = shl <4 x i32> [[TMP34]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHL30]], ptr @si, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SHL31:%.*]] = shl <4 x i32> [[TMP35]], [[TMP36]] -// CHECK: store volatile <4 x i32> [[SHL31]], ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[SHL32:%.*]] = shl <4 x i32> [[TMP37]], [[TMP38]] -// CHECK: store volatile <4 x i32> [[SHL32]], ptr @ui, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP40:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP40]], i64 0 -// CHECK: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[SHL35:%.*]] = shl <4 x i32> [[TMP39]], [[SPLAT_SPLAT34]] -// CHECK: store volatile <4 x i32> [[SHL35]], ptr @ui, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHL36:%.*]] = shl <4 x i32> [[TMP41]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHL36]], ptr @ui, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SHL37:%.*]] = shl <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[SHL37]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[SHL38:%.*]] = shl <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[SHL38]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP47]], i64 0 -// CHECK: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> -// CHECK: [[SHL42:%.*]] = shl <2 x i64> [[TMP46]], [[SH_PROM41]] -// CHECK: store volatile <2 x i64> [[SHL42]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHL43:%.*]] = shl <2 x i64> [[TMP48]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHL43]], ptr @sl, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SHL44:%.*]] = shl <2 x i64> [[TMP49]], [[TMP50]] -// CHECK: store volatile <2 x i64> [[SHL44]], ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[SHL45:%.*]] = shl <2 x i64> [[TMP51]], [[TMP52]] -// CHECK: store volatile <2 x i64> [[SHL45]], ptr @ul, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP54:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP54]], i64 0 -// CHECK: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> -// CHECK: [[SHL49:%.*]] = shl <2 x i64> [[TMP53]], [[SH_PROM48]] -// CHECK: store volatile <2 x i64> [[SHL49]], ptr @ul, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHL50:%.*]] = shl <2 x i64> [[TMP55]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHL50]], ptr @ul, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_sl( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[SHL1:%.*]] = shl <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP5]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> +// CHECK-NEXT: [[SHL2:%.*]] = shl <16 x i8> [[TMP4]], [[SH_PROM]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHL3:%.*]] = shl <16 x i8> [[TMP6]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHL3]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SHL4:%.*]] = shl <16 x i8> [[TMP7]], [[TMP8]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[SHL5:%.*]] = shl <16 x i8> [[TMP9]], [[TMP10]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP12]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> +// CHECK-NEXT: [[SHL9:%.*]] = shl <16 x i8> [[TMP11]], [[SH_PROM8]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL9]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHL10:%.*]] = shl <16 x i8> [[TMP13]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHL10]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SHL11:%.*]] = shl <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL11]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[SHL12:%.*]] = shl <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL12]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP19]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> +// CHECK-NEXT: [[SHL16:%.*]] = shl <8 x i16> [[TMP18]], [[SH_PROM15]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL16]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHL17:%.*]] = shl <8 x i16> [[TMP20]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHL17]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SHL18:%.*]] = shl <8 x i16> [[TMP21]], [[TMP22]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL18]], ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[SHL19:%.*]] = shl <8 x i16> [[TMP23]], [[TMP24]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL19]], ptr @us, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP26]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> +// CHECK-NEXT: [[SHL23:%.*]] = shl <8 x i16> [[TMP25]], [[SH_PROM22]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL23]], ptr @us, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHL24:%.*]] = shl <8 x i16> [[TMP27]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHL24]], ptr @us, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SHL25:%.*]] = shl <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL25]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[SHL26:%.*]] = shl <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL26]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP33]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[SHL29:%.*]] = shl <4 x i32> [[TMP32]], [[SPLAT_SPLAT28]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL29]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHL30:%.*]] = shl <4 x i32> [[TMP34]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHL30]], ptr @si, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SHL31:%.*]] = shl <4 x i32> [[TMP35]], [[TMP36]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL31]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[SHL32:%.*]] = shl <4 x i32> [[TMP37]], [[TMP38]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL32]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP40]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[SHL35:%.*]] = shl <4 x i32> [[TMP39]], [[SPLAT_SPLAT34]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL35]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHL36:%.*]] = shl <4 x i32> [[TMP41]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHL36]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SHL37:%.*]] = shl <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL37]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[SHL38:%.*]] = shl <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL38]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP47]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> +// CHECK-NEXT: [[SHL42:%.*]] = shl <2 x i64> [[TMP46]], [[SH_PROM41]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL42]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHL43:%.*]] = shl <2 x i64> [[TMP48]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHL43]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SHL44:%.*]] = shl <2 x i64> [[TMP49]], [[TMP50]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL44]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[SHL45:%.*]] = shl <2 x i64> [[TMP51]], [[TMP52]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL45]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP54]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> +// CHECK-NEXT: [[SHL49:%.*]] = shl <2 x i64> [[TMP53]], [[SH_PROM48]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL49]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHL50:%.*]] = shl <2 x i64> [[TMP55]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHL50]], ptr @ul, align 8 +// CHECK-NEXT: ret void +// void test_sl(void) { sc = sc << sc2; @@ -2098,150 +2174,153 @@ void test_sl(void) { ul = ul << 5; } -// CHECK-LABEL: define{{.*}} void @test_sl_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHL:%.*]] = shl <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[SHL]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHL1:%.*]] = shl <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[SHL1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP4]], i64 0 -// CHECK: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLAT:%.*]]insert, <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> -// CHECK: [[SHL2:%.*]] = shl <16 x i8> [[TMP5]], [[SH_PROM]] -// CHECK: store volatile <16 x i8> [[SHL2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHL3:%.*]] = shl <16 x i8> [[TMP6]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHL3]], ptr @sc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHL4:%.*]] = shl <16 x i8> [[TMP8]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[SHL4]], ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHL5:%.*]] = shl <16 x i8> [[TMP10]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[SHL5]], ptr @uc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP11]], i64 0 -// CHECK: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> -// CHECK: [[SHL9:%.*]] = shl <16 x i8> [[TMP12]], [[SH_PROM8]] -// CHECK: store volatile <16 x i8> [[SHL9]], ptr @uc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHL10:%.*]] = shl <16 x i8> [[TMP13]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHL10]], ptr @uc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHL11:%.*]] = shl <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[SHL11]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHL12:%.*]] = shl <8 x i16> [[TMP17]], [[TMP16]] -// CHECK: store volatile <8 x i16> [[SHL12]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP18]], i64 0 -// CHECK: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> -// CHECK: [[SHL16:%.*]] = shl <8 x i16> [[TMP19]], [[SH_PROM15]] -// CHECK: store volatile <8 x i16> [[SHL16]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHL17:%.*]] = shl <8 x i16> [[TMP20]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHL17]], ptr @ss, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHL18:%.*]] = shl <8 x i16> [[TMP22]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[SHL18]], ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHL19:%.*]] = shl <8 x i16> [[TMP24]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[SHL19]], ptr @us, align 8 -// CHECK: [[TMP25:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP25]], i64 0 -// CHECK: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> -// CHECK: [[SHL23:%.*]] = shl <8 x i16> [[TMP26]], [[SH_PROM22]] -// CHECK: store volatile <8 x i16> [[SHL23]], ptr @us, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHL24:%.*]] = shl <8 x i16> [[TMP27]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHL24]], ptr @us, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHL25:%.*]] = shl <4 x i32> [[TMP29]], [[TMP28]] -// CHECK: store volatile <4 x i32> [[SHL25]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHL26:%.*]] = shl <4 x i32> [[TMP31]], [[TMP30]] -// CHECK: store volatile <4 x i32> [[SHL26]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP32]], i64 0 -// CHECK: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHL29:%.*]] = shl <4 x i32> [[TMP33]], [[SPLAT_SPLAT28]] -// CHECK: store volatile <4 x i32> [[SHL29]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHL30:%.*]] = shl <4 x i32> [[TMP34]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHL30]], ptr @si, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHL31:%.*]] = shl <4 x i32> [[TMP36]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[SHL31]], ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHL32:%.*]] = shl <4 x i32> [[TMP38]], [[TMP37]] -// CHECK: store volatile <4 x i32> [[SHL32]], ptr @ui, align 8 -// CHECK: [[TMP39:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP39]], i64 0 -// CHECK: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHL35:%.*]] = shl <4 x i32> [[TMP40]], [[SPLAT_SPLAT34]] -// CHECK: store volatile <4 x i32> [[SHL35]], ptr @ui, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHL36:%.*]] = shl <4 x i32> [[TMP41]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHL36]], ptr @ui, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHL37:%.*]] = shl <2 x i64> [[TMP43]], [[TMP42]] -// CHECK: store volatile <2 x i64> [[SHL37]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHL38:%.*]] = shl <2 x i64> [[TMP45]], [[TMP44]] -// CHECK: store volatile <2 x i64> [[SHL38]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP46]], i64 0 -// CHECK: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> -// CHECK: [[SHL42:%.*]] = shl <2 x i64> [[TMP47]], [[SH_PROM41]] -// CHECK: store volatile <2 x i64> [[SHL42]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHL43:%.*]] = shl <2 x i64> [[TMP48]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHL43]], ptr @sl, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHL44:%.*]] = shl <2 x i64> [[TMP50]], [[TMP49]] -// CHECK: store volatile <2 x i64> [[SHL44]], ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHL45:%.*]] = shl <2 x i64> [[TMP52]], [[TMP51]] -// CHECK: store volatile <2 x i64> [[SHL45]], ptr @ul, align 8 -// CHECK: [[TMP53:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP53]], i64 0 -// CHECK: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> -// CHECK: [[SHL49:%.*]] = shl <2 x i64> [[TMP54]], [[SH_PROM48]] -// CHECK: store volatile <2 x i64> [[SHL49]], ptr @ul, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHL50:%.*]] = shl <2 x i64> [[TMP55]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHL50]], ptr @ul, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_sl_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHL:%.*]] = shl <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHL1:%.*]] = shl <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP4]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> +// CHECK-NEXT: [[SHL2:%.*]] = shl <16 x i8> [[TMP5]], [[SH_PROM]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHL3:%.*]] = shl <16 x i8> [[TMP6]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHL3]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHL4:%.*]] = shl <16 x i8> [[TMP8]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHL5:%.*]] = shl <16 x i8> [[TMP10]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP11]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> +// CHECK-NEXT: [[SHL9:%.*]] = shl <16 x i8> [[TMP12]], [[SH_PROM8]] +// CHECK-NEXT: store volatile <16 x i8> [[SHL9]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHL10:%.*]] = shl <16 x i8> [[TMP13]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHL10]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHL11:%.*]] = shl <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL11]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHL12:%.*]] = shl <8 x i16> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL12]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP18]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> +// CHECK-NEXT: [[SHL16:%.*]] = shl <8 x i16> [[TMP19]], [[SH_PROM15]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL16]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHL17:%.*]] = shl <8 x i16> [[TMP20]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHL17]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHL18:%.*]] = shl <8 x i16> [[TMP22]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL18]], ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHL19:%.*]] = shl <8 x i16> [[TMP24]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL19]], ptr @us, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP25]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> +// CHECK-NEXT: [[SHL23:%.*]] = shl <8 x i16> [[TMP26]], [[SH_PROM22]] +// CHECK-NEXT: store volatile <8 x i16> [[SHL23]], ptr @us, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHL24:%.*]] = shl <8 x i16> [[TMP27]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHL24]], ptr @us, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHL25:%.*]] = shl <4 x i32> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL25]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHL26:%.*]] = shl <4 x i32> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL26]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP32]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHL29:%.*]] = shl <4 x i32> [[TMP33]], [[SPLAT_SPLAT28]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL29]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHL30:%.*]] = shl <4 x i32> [[TMP34]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHL30]], ptr @si, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHL31:%.*]] = shl <4 x i32> [[TMP36]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL31]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHL32:%.*]] = shl <4 x i32> [[TMP38]], [[TMP37]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL32]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP39]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHL35:%.*]] = shl <4 x i32> [[TMP40]], [[SPLAT_SPLAT34]] +// CHECK-NEXT: store volatile <4 x i32> [[SHL35]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHL36:%.*]] = shl <4 x i32> [[TMP41]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHL36]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHL37:%.*]] = shl <2 x i64> [[TMP43]], [[TMP42]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL37]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHL38:%.*]] = shl <2 x i64> [[TMP45]], [[TMP44]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL38]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP46]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> +// CHECK-NEXT: [[SHL42:%.*]] = shl <2 x i64> [[TMP47]], [[SH_PROM41]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL42]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHL43:%.*]] = shl <2 x i64> [[TMP48]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHL43]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHL44:%.*]] = shl <2 x i64> [[TMP50]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL44]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHL45:%.*]] = shl <2 x i64> [[TMP52]], [[TMP51]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL45]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP53]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> +// CHECK-NEXT: [[SHL49:%.*]] = shl <2 x i64> [[TMP54]], [[SH_PROM48]] +// CHECK-NEXT: store volatile <2 x i64> [[SHL49]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHL50:%.*]] = shl <2 x i64> [[TMP55]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHL50]], ptr @ul, align 8 +// CHECK-NEXT: ret void +// void test_sl_assign(void) { sc <<= sc2; @@ -2281,150 +2360,153 @@ void test_sl_assign(void) { ul <<= 5; } -// CHECK-LABEL: define{{.*}} void @test_sr() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SHR:%.*]] = ashr <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: store volatile <16 x i8> [[SHR]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[SHR1:%.*]] = ashr <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: store volatile <16 x i8> [[SHR1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP5]], i64 0 -// CHECK: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLAT:%.*]]insert, <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> -// CHECK: [[SHR2:%.*]] = ashr <16 x i8> [[TMP4]], [[SH_PROM]] -// CHECK: store volatile <16 x i8> [[SHR2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHR3:%.*]] = ashr <16 x i8> [[TMP6]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHR3]], ptr @sc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[SHR4:%.*]] = lshr <16 x i8> [[TMP7]], [[TMP8]] -// CHECK: store volatile <16 x i8> [[SHR4]], ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[SHR5:%.*]] = lshr <16 x i8> [[TMP9]], [[TMP10]] -// CHECK: store volatile <16 x i8> [[SHR5]], ptr @uc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP12]], i64 0 -// CHECK: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> -// CHECK: [[SHR9:%.*]] = lshr <16 x i8> [[TMP11]], [[SH_PROM8]] -// CHECK: store volatile <16 x i8> [[SHR9]], ptr @uc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHR10:%.*]] = lshr <16 x i8> [[TMP13]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHR10]], ptr @uc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SHR11:%.*]] = ashr <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: store volatile <8 x i16> [[SHR11]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[SHR12:%.*]] = ashr <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: store volatile <8 x i16> [[SHR12]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP19:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP19]], i64 0 -// CHECK: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> -// CHECK: [[SHR16:%.*]] = ashr <8 x i16> [[TMP18]], [[SH_PROM15]] -// CHECK: store volatile <8 x i16> [[SHR16]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHR17:%.*]] = ashr <8 x i16> [[TMP20]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHR17]], ptr @ss, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[SHR18:%.*]] = lshr <8 x i16> [[TMP21]], [[TMP22]] -// CHECK: store volatile <8 x i16> [[SHR18]], ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[SHR19:%.*]] = lshr <8 x i16> [[TMP23]], [[TMP24]] -// CHECK: store volatile <8 x i16> [[SHR19]], ptr @us, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP26:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP26]], i64 0 -// CHECK: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> -// CHECK: [[SHR23:%.*]] = lshr <8 x i16> [[TMP25]], [[SH_PROM22]] -// CHECK: store volatile <8 x i16> [[SHR23]], ptr @us, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHR24:%.*]] = lshr <8 x i16> [[TMP27]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHR24]], ptr @us, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SHR25:%.*]] = ashr <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: store volatile <4 x i32> [[SHR25]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[SHR26:%.*]] = ashr <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: store volatile <4 x i32> [[SHR26]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP33:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP33]], i64 0 -// CHECK: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[SHR29:%.*]] = ashr <4 x i32> [[TMP32]], [[SPLAT_SPLAT28]] -// CHECK: store volatile <4 x i32> [[SHR29]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHR30:%.*]] = ashr <4 x i32> [[TMP34]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHR30]], ptr @si, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[SHR31:%.*]] = lshr <4 x i32> [[TMP35]], [[TMP36]] -// CHECK: store volatile <4 x i32> [[SHR31]], ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[SHR32:%.*]] = lshr <4 x i32> [[TMP37]], [[TMP38]] -// CHECK: store volatile <4 x i32> [[SHR32]], ptr @ui, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP40:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP40]], i64 0 -// CHECK: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[SHR35:%.*]] = lshr <4 x i32> [[TMP39]], [[SPLAT_SPLAT34]] -// CHECK: store volatile <4 x i32> [[SHR35]], ptr @ui, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHR36:%.*]] = lshr <4 x i32> [[TMP41]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHR36]], ptr @ui, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SHR37:%.*]] = ashr <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: store volatile <2 x i64> [[SHR37]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[SHR38:%.*]] = ashr <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: store volatile <2 x i64> [[SHR38]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP47]], i64 0 -// CHECK: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> -// CHECK: [[SHR42:%.*]] = ashr <2 x i64> [[TMP46]], [[SH_PROM41]] -// CHECK: store volatile <2 x i64> [[SHR42]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHR43:%.*]] = ashr <2 x i64> [[TMP48]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHR43]], ptr @sl, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[SHR44:%.*]] = lshr <2 x i64> [[TMP49]], [[TMP50]] -// CHECK: store volatile <2 x i64> [[SHR44]], ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[SHR45:%.*]] = lshr <2 x i64> [[TMP51]], [[TMP52]] -// CHECK: store volatile <2 x i64> [[SHR45]], ptr @ul, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP54:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP54]], i64 0 -// CHECK: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> -// CHECK: [[SHR49:%.*]] = lshr <2 x i64> [[TMP53]], [[SH_PROM48]] -// CHECK: store volatile <2 x i64> [[SHR49]], ptr @ul, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHR50:%.*]] = lshr <2 x i64> [[TMP55]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHR50]], ptr @ul, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_sr( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SHR:%.*]] = ashr <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[SHR1:%.*]] = ashr <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP5]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> +// CHECK-NEXT: [[SHR2:%.*]] = ashr <16 x i8> [[TMP4]], [[SH_PROM]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHR3:%.*]] = ashr <16 x i8> [[TMP6]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHR3]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[SHR4:%.*]] = lshr <16 x i8> [[TMP7]], [[TMP8]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[SHR5:%.*]] = lshr <16 x i8> [[TMP9]], [[TMP10]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP12]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> +// CHECK-NEXT: [[SHR9:%.*]] = lshr <16 x i8> [[TMP11]], [[SH_PROM8]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR9]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHR10:%.*]] = lshr <16 x i8> [[TMP13]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHR10]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SHR11:%.*]] = ashr <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR11]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[SHR12:%.*]] = ashr <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR12]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP19]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> +// CHECK-NEXT: [[SHR16:%.*]] = ashr <8 x i16> [[TMP18]], [[SH_PROM15]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR16]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHR17:%.*]] = ashr <8 x i16> [[TMP20]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHR17]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[SHR18:%.*]] = lshr <8 x i16> [[TMP21]], [[TMP22]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR18]], ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[SHR19:%.*]] = lshr <8 x i16> [[TMP23]], [[TMP24]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR19]], ptr @us, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP26]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> +// CHECK-NEXT: [[SHR23:%.*]] = lshr <8 x i16> [[TMP25]], [[SH_PROM22]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR23]], ptr @us, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHR24:%.*]] = lshr <8 x i16> [[TMP27]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHR24]], ptr @us, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SHR25:%.*]] = ashr <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR25]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[SHR26:%.*]] = ashr <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR26]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP33]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[SHR29:%.*]] = ashr <4 x i32> [[TMP32]], [[SPLAT_SPLAT28]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR29]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHR30:%.*]] = ashr <4 x i32> [[TMP34]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHR30]], ptr @si, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[SHR31:%.*]] = lshr <4 x i32> [[TMP35]], [[TMP36]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR31]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[SHR32:%.*]] = lshr <4 x i32> [[TMP37]], [[TMP38]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR32]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP40]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[SHR35:%.*]] = lshr <4 x i32> [[TMP39]], [[SPLAT_SPLAT34]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR35]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHR36:%.*]] = lshr <4 x i32> [[TMP41]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHR36]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SHR37:%.*]] = ashr <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR37]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[SHR38:%.*]] = ashr <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR38]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP47]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> +// CHECK-NEXT: [[SHR42:%.*]] = ashr <2 x i64> [[TMP46]], [[SH_PROM41]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR42]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHR43:%.*]] = ashr <2 x i64> [[TMP48]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHR43]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[SHR44:%.*]] = lshr <2 x i64> [[TMP49]], [[TMP50]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR44]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[SHR45:%.*]] = lshr <2 x i64> [[TMP51]], [[TMP52]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR45]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP54]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> +// CHECK-NEXT: [[SHR49:%.*]] = lshr <2 x i64> [[TMP53]], [[SH_PROM48]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR49]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHR50:%.*]] = lshr <2 x i64> [[TMP55]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHR50]], ptr @ul, align 8 +// CHECK-NEXT: ret void +// void test_sr(void) { sc = sc >> sc2; @@ -2464,150 +2546,153 @@ void test_sr(void) { ul = ul >> 5; } -// CHECK-LABEL: define{{.*}} void @test_sr_assign() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHR:%.*]] = ashr <16 x i8> [[TMP1]], [[TMP0]] -// CHECK: store volatile <16 x i8> [[SHR]], ptr @sc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHR1:%.*]] = ashr <16 x i8> [[TMP3]], [[TMP2]] -// CHECK: store volatile <16 x i8> [[SHR1]], ptr @sc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP4]], i64 0 -// CHECK: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLAT:%.*]]insert, <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> -// CHECK: [[SHR2:%.*]] = ashr <16 x i8> [[TMP5]], [[SH_PROM]] -// CHECK: store volatile <16 x i8> [[SHR2]], ptr @sc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[SHR3:%.*]] = ashr <16 x i8> [[TMP6]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHR3]], ptr @sc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHR4:%.*]] = lshr <16 x i8> [[TMP8]], [[TMP7]] -// CHECK: store volatile <16 x i8> [[SHR4]], ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHR5:%.*]] = lshr <16 x i8> [[TMP10]], [[TMP9]] -// CHECK: store volatile <16 x i8> [[SHR5]], ptr @uc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP11]], i64 0 -// CHECK: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> -// CHECK: [[SHR9:%.*]] = lshr <16 x i8> [[TMP12]], [[SH_PROM8]] -// CHECK: store volatile <16 x i8> [[SHR9]], ptr @uc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[SHR10:%.*]] = lshr <16 x i8> [[TMP13]], splat (i8 5) -// CHECK: store volatile <16 x i8> [[SHR10]], ptr @uc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHR11:%.*]] = ashr <8 x i16> [[TMP15]], [[TMP14]] -// CHECK: store volatile <8 x i16> [[SHR11]], ptr @ss, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHR12:%.*]] = ashr <8 x i16> [[TMP17]], [[TMP16]] -// CHECK: store volatile <8 x i16> [[SHR12]], ptr @ss, align 8 -// CHECK: [[TMP18:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP18]], i64 0 -// CHECK: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> -// CHECK: [[SHR16:%.*]] = ashr <8 x i16> [[TMP19]], [[SH_PROM15]] -// CHECK: store volatile <8 x i16> [[SHR16]], ptr @ss, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[SHR17:%.*]] = ashr <8 x i16> [[TMP20]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHR17]], ptr @ss, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHR18:%.*]] = lshr <8 x i16> [[TMP22]], [[TMP21]] -// CHECK: store volatile <8 x i16> [[SHR18]], ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHR19:%.*]] = lshr <8 x i16> [[TMP24]], [[TMP23]] -// CHECK: store volatile <8 x i16> [[SHR19]], ptr @us, align 8 -// CHECK: [[TMP25:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP25]], i64 0 -// CHECK: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> -// CHECK: [[SHR23:%.*]] = lshr <8 x i16> [[TMP26]], [[SH_PROM22]] -// CHECK: store volatile <8 x i16> [[SHR23]], ptr @us, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[SHR24:%.*]] = lshr <8 x i16> [[TMP27]], splat (i16 5) -// CHECK: store volatile <8 x i16> [[SHR24]], ptr @us, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHR25:%.*]] = ashr <4 x i32> [[TMP29]], [[TMP28]] -// CHECK: store volatile <4 x i32> [[SHR25]], ptr @si, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHR26:%.*]] = ashr <4 x i32> [[TMP31]], [[TMP30]] -// CHECK: store volatile <4 x i32> [[SHR26]], ptr @si, align 8 -// CHECK: [[TMP32:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP32]], i64 0 -// CHECK: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHR29:%.*]] = ashr <4 x i32> [[TMP33]], [[SPLAT_SPLAT28]] -// CHECK: store volatile <4 x i32> [[SHR29]], ptr @si, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[SHR30:%.*]] = ashr <4 x i32> [[TMP34]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHR30]], ptr @si, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHR31:%.*]] = lshr <4 x i32> [[TMP36]], [[TMP35]] -// CHECK: store volatile <4 x i32> [[SHR31]], ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHR32:%.*]] = lshr <4 x i32> [[TMP38]], [[TMP37]] -// CHECK: store volatile <4 x i32> [[SHR32]], ptr @ui, align 8 -// CHECK: [[TMP39:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP39]], i64 0 -// CHECK: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHR35:%.*]] = lshr <4 x i32> [[TMP40]], [[SPLAT_SPLAT34]] -// CHECK: store volatile <4 x i32> [[SHR35]], ptr @ui, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[SHR36:%.*]] = lshr <4 x i32> [[TMP41]], splat (i32 5) -// CHECK: store volatile <4 x i32> [[SHR36]], ptr @ui, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHR37:%.*]] = ashr <2 x i64> [[TMP43]], [[TMP42]] -// CHECK: store volatile <2 x i64> [[SHR37]], ptr @sl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHR38:%.*]] = ashr <2 x i64> [[TMP45]], [[TMP44]] -// CHECK: store volatile <2 x i64> [[SHR38]], ptr @sl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP46]], i64 0 -// CHECK: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> -// CHECK: [[SHR42:%.*]] = ashr <2 x i64> [[TMP47]], [[SH_PROM41]] -// CHECK: store volatile <2 x i64> [[SHR42]], ptr @sl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[SHR43:%.*]] = ashr <2 x i64> [[TMP48]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHR43]], ptr @sl, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHR44:%.*]] = lshr <2 x i64> [[TMP50]], [[TMP49]] -// CHECK: store volatile <2 x i64> [[SHR44]], ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHR45:%.*]] = lshr <2 x i64> [[TMP52]], [[TMP51]] -// CHECK: store volatile <2 x i64> [[SHR45]], ptr @ul, align 8 -// CHECK: [[TMP53:%.*]] = load volatile i32, ptr @cnt, align 4 -// CHECK: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP53]], i64 0 -// CHECK: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> -// CHECK: [[SHR49:%.*]] = lshr <2 x i64> [[TMP54]], [[SH_PROM48]] -// CHECK: store volatile <2 x i64> [[SHR49]], ptr @ul, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[SHR50:%.*]] = lshr <2 x i64> [[TMP55]], splat (i64 5) -// CHECK: store volatile <2 x i64> [[SHR50]], ptr @ul, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_sr_assign( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHR:%.*]] = ashr <16 x i8> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHR1:%.*]] = ashr <16 x i8> [[TMP3]], [[TMP2]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR1]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i32> poison, i32 [[TMP4]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SH_PROM:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT]] to <16 x i8> +// CHECK-NEXT: [[SHR2:%.*]] = ashr <16 x i8> [[TMP5]], [[SH_PROM]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR2]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[SHR3:%.*]] = ashr <16 x i8> [[TMP6]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHR3]], ptr @sc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHR4:%.*]] = lshr <16 x i8> [[TMP8]], [[TMP7]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR4]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHR5:%.*]] = lshr <16 x i8> [[TMP10]], [[TMP9]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR5]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <16 x i32> poison, i32 [[TMP11]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <16 x i32> [[SPLAT_SPLATINSERT6]], <16 x i32> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SH_PROM8:%.*]] = trunc <16 x i32> [[SPLAT_SPLAT7]] to <16 x i8> +// CHECK-NEXT: [[SHR9:%.*]] = lshr <16 x i8> [[TMP12]], [[SH_PROM8]] +// CHECK-NEXT: store volatile <16 x i8> [[SHR9]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[SHR10:%.*]] = lshr <16 x i8> [[TMP13]], splat (i8 5) +// CHECK-NEXT: store volatile <16 x i8> [[SHR10]], ptr @uc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHR11:%.*]] = ashr <8 x i16> [[TMP15]], [[TMP14]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR11]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHR12:%.*]] = ashr <8 x i16> [[TMP17]], [[TMP16]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR12]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <8 x i32> poison, i32 [[TMP18]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT13]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SH_PROM15:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT14]] to <8 x i16> +// CHECK-NEXT: [[SHR16:%.*]] = ashr <8 x i16> [[TMP19]], [[SH_PROM15]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR16]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[SHR17:%.*]] = ashr <8 x i16> [[TMP20]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHR17]], ptr @ss, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHR18:%.*]] = lshr <8 x i16> [[TMP22]], [[TMP21]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR18]], ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHR19:%.*]] = lshr <8 x i16> [[TMP24]], [[TMP23]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR19]], ptr @us, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT20:%.*]] = insertelement <8 x i32> poison, i32 [[TMP25]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT21:%.*]] = shufflevector <8 x i32> [[SPLAT_SPLATINSERT20]], <8 x i32> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SH_PROM22:%.*]] = trunc <8 x i32> [[SPLAT_SPLAT21]] to <8 x i16> +// CHECK-NEXT: [[SHR23:%.*]] = lshr <8 x i16> [[TMP26]], [[SH_PROM22]] +// CHECK-NEXT: store volatile <8 x i16> [[SHR23]], ptr @us, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[SHR24:%.*]] = lshr <8 x i16> [[TMP27]], splat (i16 5) +// CHECK-NEXT: store volatile <8 x i16> [[SHR24]], ptr @us, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHR25:%.*]] = ashr <4 x i32> [[TMP29]], [[TMP28]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR25]], ptr @si, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHR26:%.*]] = ashr <4 x i32> [[TMP31]], [[TMP30]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR26]], ptr @si, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT27:%.*]] = insertelement <4 x i32> poison, i32 [[TMP32]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT28:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT27]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHR29:%.*]] = ashr <4 x i32> [[TMP33]], [[SPLAT_SPLAT28]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR29]], ptr @si, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[SHR30:%.*]] = ashr <4 x i32> [[TMP34]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHR30]], ptr @si, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHR31:%.*]] = lshr <4 x i32> [[TMP36]], [[TMP35]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR31]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHR32:%.*]] = lshr <4 x i32> [[TMP38]], [[TMP37]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR32]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT33:%.*]] = insertelement <4 x i32> poison, i32 [[TMP39]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT34:%.*]] = shufflevector <4 x i32> [[SPLAT_SPLATINSERT33]], <4 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHR35:%.*]] = lshr <4 x i32> [[TMP40]], [[SPLAT_SPLAT34]] +// CHECK-NEXT: store volatile <4 x i32> [[SHR35]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[SHR36:%.*]] = lshr <4 x i32> [[TMP41]], splat (i32 5) +// CHECK-NEXT: store volatile <4 x i32> [[SHR36]], ptr @ui, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHR37:%.*]] = ashr <2 x i64> [[TMP43]], [[TMP42]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR37]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHR38:%.*]] = ashr <2 x i64> [[TMP45]], [[TMP44]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR38]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT39:%.*]] = insertelement <2 x i32> poison, i32 [[TMP46]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT40:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT39]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SH_PROM41:%.*]] = zext <2 x i32> [[SPLAT_SPLAT40]] to <2 x i64> +// CHECK-NEXT: [[SHR42:%.*]] = ashr <2 x i64> [[TMP47]], [[SH_PROM41]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR42]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[SHR43:%.*]] = ashr <2 x i64> [[TMP48]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHR43]], ptr @sl, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHR44:%.*]] = lshr <2 x i64> [[TMP50]], [[TMP49]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR44]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHR45:%.*]] = lshr <2 x i64> [[TMP52]], [[TMP51]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR45]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile i32, ptr @cnt, align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT46:%.*]] = insertelement <2 x i32> poison, i32 [[TMP53]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT47:%.*]] = shufflevector <2 x i32> [[SPLAT_SPLATINSERT46]], <2 x i32> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SH_PROM48:%.*]] = zext <2 x i32> [[SPLAT_SPLAT47]] to <2 x i64> +// CHECK-NEXT: [[SHR49:%.*]] = lshr <2 x i64> [[TMP54]], [[SH_PROM48]] +// CHECK-NEXT: store volatile <2 x i64> [[SHR49]], ptr @ul, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[SHR50:%.*]] = lshr <2 x i64> [[TMP55]], splat (i64 5) +// CHECK-NEXT: store volatile <2 x i64> [[SHR50]], ptr @ul, align 8 +// CHECK-NEXT: ret void +// void test_sr_assign(void) { sc >>= sc2; @@ -2648,153 +2733,156 @@ void test_sr_assign(void) { } -// CHECK-LABEL: define{{.*}} void @test_cmpeq() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP:%.*]] = icmp eq <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP1:%.*]] = icmp eq <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP3:%.*]] = icmp eq <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP5:%.*]] = icmp eq <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: [[SEXT6:%.*]] = sext <16 x i1> [[CMP5]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT6]], ptr @bc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP7:%.*]] = icmp eq <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: [[SEXT8:%.*]] = sext <16 x i1> [[CMP7]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT8]], ptr @bc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP9:%.*]] = icmp eq <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: [[SEXT10:%.*]] = sext <16 x i1> [[CMP9]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT10]], ptr @bc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP11:%.*]] = icmp eq <16 x i8> [[TMP12]], [[TMP13]] -// CHECK: [[SEXT12:%.*]] = sext <16 x i1> [[CMP11]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT12]], ptr @bc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP13:%.*]] = icmp eq <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: [[SEXT14:%.*]] = sext <8 x i1> [[CMP13]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT14]], ptr @bs, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP15:%.*]] = icmp eq <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: [[SEXT16:%.*]] = sext <8 x i1> [[CMP15]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT16]], ptr @bs, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP17:%.*]] = icmp eq <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: [[SEXT18:%.*]] = sext <8 x i1> [[CMP17]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT18]], ptr @bs, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP19:%.*]] = icmp eq <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: [[SEXT20:%.*]] = sext <8 x i1> [[CMP19]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT20]], ptr @bs, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP21:%.*]] = icmp eq <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: [[SEXT22:%.*]] = sext <8 x i1> [[CMP21]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT22]], ptr @bs, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP23:%.*]] = icmp eq <8 x i16> [[TMP24]], [[TMP25]] -// CHECK: [[SEXT24:%.*]] = sext <8 x i1> [[CMP23]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT24]], ptr @bs, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP25:%.*]] = icmp eq <8 x i16> [[TMP26]], [[TMP27]] -// CHECK: [[SEXT26:%.*]] = sext <8 x i1> [[CMP25]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT26]], ptr @bs, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP27:%.*]] = icmp eq <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: [[SEXT28:%.*]] = sext <4 x i1> [[CMP27]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT28]], ptr @bi, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP29:%.*]] = icmp eq <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: [[SEXT30:%.*]] = sext <4 x i1> [[CMP29]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT30]], ptr @bi, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP31:%.*]] = icmp eq <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: [[SEXT32:%.*]] = sext <4 x i1> [[CMP31]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT32]], ptr @bi, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP33:%.*]] = icmp eq <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: [[SEXT34:%.*]] = sext <4 x i1> [[CMP33]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT34]], ptr @bi, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP35:%.*]] = icmp eq <4 x i32> [[TMP36]], [[TMP37]] -// CHECK: [[SEXT36:%.*]] = sext <4 x i1> [[CMP35]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT36]], ptr @bi, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP37:%.*]] = icmp eq <4 x i32> [[TMP38]], [[TMP39]] -// CHECK: [[SEXT38:%.*]] = sext <4 x i1> [[CMP37]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT38]], ptr @bi, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP39:%.*]] = icmp eq <4 x i32> [[TMP40]], [[TMP41]] -// CHECK: [[SEXT40:%.*]] = sext <4 x i1> [[CMP39]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT40]], ptr @bi, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP41:%.*]] = icmp eq <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: [[SEXT42:%.*]] = sext <2 x i1> [[CMP41]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT42]], ptr @bl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP43:%.*]] = icmp eq <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: [[SEXT44:%.*]] = sext <2 x i1> [[CMP43]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT44]], ptr @bl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP45:%.*]] = icmp eq <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: [[SEXT46:%.*]] = sext <2 x i1> [[CMP45]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT46]], ptr @bl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP47:%.*]] = icmp eq <2 x i64> [[TMP48]], [[TMP49]] -// CHECK: [[SEXT48:%.*]] = sext <2 x i1> [[CMP47]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT48]], ptr @bl, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP49:%.*]] = icmp eq <2 x i64> [[TMP50]], [[TMP51]] -// CHECK: [[SEXT50:%.*]] = sext <2 x i1> [[CMP49]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT50]], ptr @bl, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP51:%.*]] = icmp eq <2 x i64> [[TMP52]], [[TMP53]] -// CHECK: [[SEXT52:%.*]] = sext <2 x i1> [[CMP51]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT52]], ptr @bl, align 8 -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP53:%.*]] = icmp eq <2 x i64> [[TMP54]], [[TMP55]] -// CHECK: [[SEXT54:%.*]] = sext <2 x i1> [[CMP53]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT54]], ptr @bl, align 8 -// CHECK: [[TMP56:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP57:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[CMP55:%.*]] = fcmp oeq <2 x double> [[TMP56]], [[TMP57]] -// CHECK: [[SEXT56:%.*]] = sext <2 x i1> [[CMP55]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT56]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_cmpeq( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP1:%.*]] = icmp eq <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP3:%.*]] = icmp eq <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP5:%.*]] = icmp eq <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: [[SEXT6:%.*]] = sext <16 x i1> [[CMP5]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT6]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP7:%.*]] = icmp eq <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: [[SEXT8:%.*]] = sext <16 x i1> [[CMP7]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT8]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP9:%.*]] = icmp eq <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: [[SEXT10:%.*]] = sext <16 x i1> [[CMP9]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT10]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP11:%.*]] = icmp eq <16 x i8> [[TMP12]], [[TMP13]] +// CHECK-NEXT: [[SEXT12:%.*]] = sext <16 x i1> [[CMP11]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT12]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP13:%.*]] = icmp eq <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: [[SEXT14:%.*]] = sext <8 x i1> [[CMP13]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT14]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP15:%.*]] = icmp eq <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: [[SEXT16:%.*]] = sext <8 x i1> [[CMP15]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT16]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP17:%.*]] = icmp eq <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: [[SEXT18:%.*]] = sext <8 x i1> [[CMP17]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT18]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP19:%.*]] = icmp eq <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: [[SEXT20:%.*]] = sext <8 x i1> [[CMP19]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT20]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP21:%.*]] = icmp eq <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[SEXT22:%.*]] = sext <8 x i1> [[CMP21]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT22]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP23:%.*]] = icmp eq <8 x i16> [[TMP24]], [[TMP25]] +// CHECK-NEXT: [[SEXT24:%.*]] = sext <8 x i1> [[CMP23]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT24]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP25:%.*]] = icmp eq <8 x i16> [[TMP26]], [[TMP27]] +// CHECK-NEXT: [[SEXT26:%.*]] = sext <8 x i1> [[CMP25]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT26]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP27:%.*]] = icmp eq <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: [[SEXT28:%.*]] = sext <4 x i1> [[CMP27]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT28]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP29:%.*]] = icmp eq <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[SEXT30:%.*]] = sext <4 x i1> [[CMP29]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT30]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP31:%.*]] = icmp eq <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: [[SEXT32:%.*]] = sext <4 x i1> [[CMP31]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT32]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP33:%.*]] = icmp eq <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: [[SEXT34:%.*]] = sext <4 x i1> [[CMP33]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT34]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP35:%.*]] = icmp eq <4 x i32> [[TMP36]], [[TMP37]] +// CHECK-NEXT: [[SEXT36:%.*]] = sext <4 x i1> [[CMP35]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT36]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP37:%.*]] = icmp eq <4 x i32> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[SEXT38:%.*]] = sext <4 x i1> [[CMP37]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT38]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP39:%.*]] = icmp eq <4 x i32> [[TMP40]], [[TMP41]] +// CHECK-NEXT: [[SEXT40:%.*]] = sext <4 x i1> [[CMP39]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT40]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP41:%.*]] = icmp eq <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: [[SEXT42:%.*]] = sext <2 x i1> [[CMP41]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT42]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP43:%.*]] = icmp eq <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: [[SEXT44:%.*]] = sext <2 x i1> [[CMP43]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT44]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP45:%.*]] = icmp eq <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: [[SEXT46:%.*]] = sext <2 x i1> [[CMP45]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT46]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP47:%.*]] = icmp eq <2 x i64> [[TMP48]], [[TMP49]] +// CHECK-NEXT: [[SEXT48:%.*]] = sext <2 x i1> [[CMP47]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT48]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP49:%.*]] = icmp eq <2 x i64> [[TMP50]], [[TMP51]] +// CHECK-NEXT: [[SEXT50:%.*]] = sext <2 x i1> [[CMP49]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT50]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP51:%.*]] = icmp eq <2 x i64> [[TMP52]], [[TMP53]] +// CHECK-NEXT: [[SEXT52:%.*]] = sext <2 x i1> [[CMP51]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT52]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP53:%.*]] = icmp eq <2 x i64> [[TMP54]], [[TMP55]] +// CHECK-NEXT: [[SEXT54:%.*]] = sext <2 x i1> [[CMP53]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT54]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP56:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP57:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[CMP55:%.*]] = fcmp oeq <2 x double> [[TMP56]], [[TMP57]] +// CHECK-NEXT: [[SEXT56:%.*]] = sext <2 x i1> [[CMP55]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT56]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_cmpeq(void) { bc = sc == sc2; @@ -2832,153 +2920,156 @@ void test_cmpeq(void) { bl = fd == fd2; } -// CHECK-LABEL: define{{.*}} void @test_cmpne() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP:%.*]] = icmp ne <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP1:%.*]] = icmp ne <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP3:%.*]] = icmp ne <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP5:%.*]] = icmp ne <16 x i8> [[TMP6]], [[TMP7]] -// CHECK: [[SEXT6:%.*]] = sext <16 x i1> [[CMP5]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT6]], ptr @bc, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP7:%.*]] = icmp ne <16 x i8> [[TMP8]], [[TMP9]] -// CHECK: [[SEXT8:%.*]] = sext <16 x i1> [[CMP7]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT8]], ptr @bc, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP9:%.*]] = icmp ne <16 x i8> [[TMP10]], [[TMP11]] -// CHECK: [[SEXT10:%.*]] = sext <16 x i1> [[CMP9]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT10]], ptr @bc, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP11:%.*]] = icmp ne <16 x i8> [[TMP12]], [[TMP13]] -// CHECK: [[SEXT12:%.*]] = sext <16 x i1> [[CMP11]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT12]], ptr @bc, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP13:%.*]] = icmp ne <8 x i16> [[TMP14]], [[TMP15]] -// CHECK: [[SEXT14:%.*]] = sext <8 x i1> [[CMP13]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT14]], ptr @bs, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP15:%.*]] = icmp ne <8 x i16> [[TMP16]], [[TMP17]] -// CHECK: [[SEXT16:%.*]] = sext <8 x i1> [[CMP15]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT16]], ptr @bs, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP17:%.*]] = icmp ne <8 x i16> [[TMP18]], [[TMP19]] -// CHECK: [[SEXT18:%.*]] = sext <8 x i1> [[CMP17]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT18]], ptr @bs, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP19:%.*]] = icmp ne <8 x i16> [[TMP20]], [[TMP21]] -// CHECK: [[SEXT20:%.*]] = sext <8 x i1> [[CMP19]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT20]], ptr @bs, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP21:%.*]] = icmp ne <8 x i16> [[TMP22]], [[TMP23]] -// CHECK: [[SEXT22:%.*]] = sext <8 x i1> [[CMP21]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT22]], ptr @bs, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP23:%.*]] = icmp ne <8 x i16> [[TMP24]], [[TMP25]] -// CHECK: [[SEXT24:%.*]] = sext <8 x i1> [[CMP23]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT24]], ptr @bs, align 8 -// CHECK: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP25:%.*]] = icmp ne <8 x i16> [[TMP26]], [[TMP27]] -// CHECK: [[SEXT26:%.*]] = sext <8 x i1> [[CMP25]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT26]], ptr @bs, align 8 -// CHECK: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP27:%.*]] = icmp ne <4 x i32> [[TMP28]], [[TMP29]] -// CHECK: [[SEXT28:%.*]] = sext <4 x i1> [[CMP27]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT28]], ptr @bi, align 8 -// CHECK: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP29:%.*]] = icmp ne <4 x i32> [[TMP30]], [[TMP31]] -// CHECK: [[SEXT30:%.*]] = sext <4 x i1> [[CMP29]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT30]], ptr @bi, align 8 -// CHECK: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP31:%.*]] = icmp ne <4 x i32> [[TMP32]], [[TMP33]] -// CHECK: [[SEXT32:%.*]] = sext <4 x i1> [[CMP31]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT32]], ptr @bi, align 8 -// CHECK: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP33:%.*]] = icmp ne <4 x i32> [[TMP34]], [[TMP35]] -// CHECK: [[SEXT34:%.*]] = sext <4 x i1> [[CMP33]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT34]], ptr @bi, align 8 -// CHECK: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP35:%.*]] = icmp ne <4 x i32> [[TMP36]], [[TMP37]] -// CHECK: [[SEXT36:%.*]] = sext <4 x i1> [[CMP35]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT36]], ptr @bi, align 8 -// CHECK: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP37:%.*]] = icmp ne <4 x i32> [[TMP38]], [[TMP39]] -// CHECK: [[SEXT38:%.*]] = sext <4 x i1> [[CMP37]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT38]], ptr @bi, align 8 -// CHECK: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP39:%.*]] = icmp ne <4 x i32> [[TMP40]], [[TMP41]] -// CHECK: [[SEXT40:%.*]] = sext <4 x i1> [[CMP39]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT40]], ptr @bi, align 8 -// CHECK: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP41:%.*]] = icmp ne <2 x i64> [[TMP42]], [[TMP43]] -// CHECK: [[SEXT42:%.*]] = sext <2 x i1> [[CMP41]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT42]], ptr @bl, align 8 -// CHECK: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP43:%.*]] = icmp ne <2 x i64> [[TMP44]], [[TMP45]] -// CHECK: [[SEXT44:%.*]] = sext <2 x i1> [[CMP43]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT44]], ptr @bl, align 8 -// CHECK: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP45:%.*]] = icmp ne <2 x i64> [[TMP46]], [[TMP47]] -// CHECK: [[SEXT46:%.*]] = sext <2 x i1> [[CMP45]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT46]], ptr @bl, align 8 -// CHECK: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP47:%.*]] = icmp ne <2 x i64> [[TMP48]], [[TMP49]] -// CHECK: [[SEXT48:%.*]] = sext <2 x i1> [[CMP47]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT48]], ptr @bl, align 8 -// CHECK: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP49:%.*]] = icmp ne <2 x i64> [[TMP50]], [[TMP51]] -// CHECK: [[SEXT50:%.*]] = sext <2 x i1> [[CMP49]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT50]], ptr @bl, align 8 -// CHECK: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP51:%.*]] = icmp ne <2 x i64> [[TMP52]], [[TMP53]] -// CHECK: [[SEXT52:%.*]] = sext <2 x i1> [[CMP51]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT52]], ptr @bl, align 8 -// CHECK: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP53:%.*]] = icmp ne <2 x i64> [[TMP54]], [[TMP55]] -// CHECK: [[SEXT54:%.*]] = sext <2 x i1> [[CMP53]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT54]], ptr @bl, align 8 -// CHECK: [[TMP56:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP57:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[CMP55:%.*]] = fcmp une <2 x double> [[TMP56]], [[TMP57]] -// CHECK: [[SEXT56:%.*]] = sext <2 x i1> [[CMP55]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT56]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_cmpne( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp ne <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP1:%.*]] = icmp ne <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP3:%.*]] = icmp ne <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP5:%.*]] = icmp ne <16 x i8> [[TMP6]], [[TMP7]] +// CHECK-NEXT: [[SEXT6:%.*]] = sext <16 x i1> [[CMP5]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT6]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP7:%.*]] = icmp ne <16 x i8> [[TMP8]], [[TMP9]] +// CHECK-NEXT: [[SEXT8:%.*]] = sext <16 x i1> [[CMP7]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT8]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP9:%.*]] = icmp ne <16 x i8> [[TMP10]], [[TMP11]] +// CHECK-NEXT: [[SEXT10:%.*]] = sext <16 x i1> [[CMP9]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT10]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP11:%.*]] = icmp ne <16 x i8> [[TMP12]], [[TMP13]] +// CHECK-NEXT: [[SEXT12:%.*]] = sext <16 x i1> [[CMP11]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT12]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP13:%.*]] = icmp ne <8 x i16> [[TMP14]], [[TMP15]] +// CHECK-NEXT: [[SEXT14:%.*]] = sext <8 x i1> [[CMP13]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT14]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP15:%.*]] = icmp ne <8 x i16> [[TMP16]], [[TMP17]] +// CHECK-NEXT: [[SEXT16:%.*]] = sext <8 x i1> [[CMP15]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT16]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP17:%.*]] = icmp ne <8 x i16> [[TMP18]], [[TMP19]] +// CHECK-NEXT: [[SEXT18:%.*]] = sext <8 x i1> [[CMP17]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT18]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP19:%.*]] = icmp ne <8 x i16> [[TMP20]], [[TMP21]] +// CHECK-NEXT: [[SEXT20:%.*]] = sext <8 x i1> [[CMP19]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT20]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP21:%.*]] = icmp ne <8 x i16> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[SEXT22:%.*]] = sext <8 x i1> [[CMP21]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT22]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP23:%.*]] = icmp ne <8 x i16> [[TMP24]], [[TMP25]] +// CHECK-NEXT: [[SEXT24:%.*]] = sext <8 x i1> [[CMP23]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT24]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP26:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP25:%.*]] = icmp ne <8 x i16> [[TMP26]], [[TMP27]] +// CHECK-NEXT: [[SEXT26:%.*]] = sext <8 x i1> [[CMP25]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT26]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP28:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP29:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP27:%.*]] = icmp ne <4 x i32> [[TMP28]], [[TMP29]] +// CHECK-NEXT: [[SEXT28:%.*]] = sext <4 x i1> [[CMP27]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT28]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP31:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP29:%.*]] = icmp ne <4 x i32> [[TMP30]], [[TMP31]] +// CHECK-NEXT: [[SEXT30:%.*]] = sext <4 x i1> [[CMP29]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT30]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP32:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP33:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP31:%.*]] = icmp ne <4 x i32> [[TMP32]], [[TMP33]] +// CHECK-NEXT: [[SEXT32:%.*]] = sext <4 x i1> [[CMP31]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT32]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP34:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP35:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP33:%.*]] = icmp ne <4 x i32> [[TMP34]], [[TMP35]] +// CHECK-NEXT: [[SEXT34:%.*]] = sext <4 x i1> [[CMP33]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT34]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP36:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP37:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP35:%.*]] = icmp ne <4 x i32> [[TMP36]], [[TMP37]] +// CHECK-NEXT: [[SEXT36:%.*]] = sext <4 x i1> [[CMP35]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT36]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP38:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP37:%.*]] = icmp ne <4 x i32> [[TMP38]], [[TMP39]] +// CHECK-NEXT: [[SEXT38:%.*]] = sext <4 x i1> [[CMP37]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT38]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP40:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP41:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP39:%.*]] = icmp ne <4 x i32> [[TMP40]], [[TMP41]] +// CHECK-NEXT: [[SEXT40:%.*]] = sext <4 x i1> [[CMP39]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT40]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP42:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP43:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP41:%.*]] = icmp ne <2 x i64> [[TMP42]], [[TMP43]] +// CHECK-NEXT: [[SEXT42:%.*]] = sext <2 x i1> [[CMP41]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT42]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP44:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP45:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP43:%.*]] = icmp ne <2 x i64> [[TMP44]], [[TMP45]] +// CHECK-NEXT: [[SEXT44:%.*]] = sext <2 x i1> [[CMP43]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT44]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP46:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP47:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP45:%.*]] = icmp ne <2 x i64> [[TMP46]], [[TMP47]] +// CHECK-NEXT: [[SEXT46:%.*]] = sext <2 x i1> [[CMP45]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT46]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP49:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP47:%.*]] = icmp ne <2 x i64> [[TMP48]], [[TMP49]] +// CHECK-NEXT: [[SEXT48:%.*]] = sext <2 x i1> [[CMP47]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT48]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP50:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP51:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP49:%.*]] = icmp ne <2 x i64> [[TMP50]], [[TMP51]] +// CHECK-NEXT: [[SEXT50:%.*]] = sext <2 x i1> [[CMP49]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT50]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP52:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP53:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP51:%.*]] = icmp ne <2 x i64> [[TMP52]], [[TMP53]] +// CHECK-NEXT: [[SEXT52:%.*]] = sext <2 x i1> [[CMP51]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT52]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP54:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP55:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP53:%.*]] = icmp ne <2 x i64> [[TMP54]], [[TMP55]] +// CHECK-NEXT: [[SEXT54:%.*]] = sext <2 x i1> [[CMP53]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT54]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP56:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP57:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[CMP55:%.*]] = fcmp une <2 x double> [[TMP56]], [[TMP57]] +// CHECK-NEXT: [[SEXT56:%.*]] = sext <2 x i1> [[CMP55]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT56]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_cmpne(void) { bc = sc != sc2; @@ -3016,73 +3107,76 @@ void test_cmpne(void) { bl = fd != fd2; } -// CHECK-LABEL: define{{.*}} void @test_cmpge() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP:%.*]] = icmp sge <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP1:%.*]] = icmp uge <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP3:%.*]] = icmp uge <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP5:%.*]] = icmp sge <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP7:%.*]] = icmp uge <8 x i16> [[TMP8]], [[TMP9]] -// CHECK: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP9:%.*]] = icmp uge <8 x i16> [[TMP10]], [[TMP11]] -// CHECK: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP11:%.*]] = icmp sge <4 x i32> [[TMP12]], [[TMP13]] -// CHECK: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP13:%.*]] = icmp uge <4 x i32> [[TMP14]], [[TMP15]] -// CHECK: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP15:%.*]] = icmp uge <4 x i32> [[TMP16]], [[TMP17]] -// CHECK: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP17:%.*]] = icmp sge <2 x i64> [[TMP18]], [[TMP19]] -// CHECK: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP19:%.*]] = icmp uge <2 x i64> [[TMP20]], [[TMP21]] -// CHECK: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP21:%.*]] = icmp uge <2 x i64> [[TMP22]], [[TMP23]] -// CHECK: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[CMP23:%.*]] = fcmp oge <2 x double> [[TMP24]], [[TMP25]] -// CHECK: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_cmpge( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp sge <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP1:%.*]] = icmp uge <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP3:%.*]] = icmp uge <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP5:%.*]] = icmp sge <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP7:%.*]] = icmp uge <8 x i16> [[TMP8]], [[TMP9]] +// CHECK-NEXT: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP9:%.*]] = icmp uge <8 x i16> [[TMP10]], [[TMP11]] +// CHECK-NEXT: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP11:%.*]] = icmp sge <4 x i32> [[TMP12]], [[TMP13]] +// CHECK-NEXT: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP13:%.*]] = icmp uge <4 x i32> [[TMP14]], [[TMP15]] +// CHECK-NEXT: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP15:%.*]] = icmp uge <4 x i32> [[TMP16]], [[TMP17]] +// CHECK-NEXT: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP17:%.*]] = icmp sge <2 x i64> [[TMP18]], [[TMP19]] +// CHECK-NEXT: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP19:%.*]] = icmp uge <2 x i64> [[TMP20]], [[TMP21]] +// CHECK-NEXT: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP21:%.*]] = icmp uge <2 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[CMP23:%.*]] = fcmp oge <2 x double> [[TMP24]], [[TMP25]] +// CHECK-NEXT: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_cmpge(void) { bc = sc >= sc2; @@ -3104,73 +3198,76 @@ void test_cmpge(void) { bl = fd >= fd2; } -// CHECK-LABEL: define{{.*}} void @test_cmpgt() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP:%.*]] = icmp sgt <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP1:%.*]] = icmp ugt <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP3:%.*]] = icmp ugt <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP5:%.*]] = icmp sgt <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP7:%.*]] = icmp ugt <8 x i16> [[TMP8]], [[TMP9]] -// CHECK: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP9:%.*]] = icmp ugt <8 x i16> [[TMP10]], [[TMP11]] -// CHECK: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP11:%.*]] = icmp sgt <4 x i32> [[TMP12]], [[TMP13]] -// CHECK: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP13:%.*]] = icmp ugt <4 x i32> [[TMP14]], [[TMP15]] -// CHECK: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP15:%.*]] = icmp ugt <4 x i32> [[TMP16]], [[TMP17]] -// CHECK: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP17:%.*]] = icmp sgt <2 x i64> [[TMP18]], [[TMP19]] -// CHECK: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP19:%.*]] = icmp ugt <2 x i64> [[TMP20]], [[TMP21]] -// CHECK: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP21:%.*]] = icmp ugt <2 x i64> [[TMP22]], [[TMP23]] -// CHECK: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[CMP23:%.*]] = fcmp ogt <2 x double> [[TMP24]], [[TMP25]] -// CHECK: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_cmpgt( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP3:%.*]] = icmp ugt <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP5:%.*]] = icmp sgt <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP7:%.*]] = icmp ugt <8 x i16> [[TMP8]], [[TMP9]] +// CHECK-NEXT: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP9:%.*]] = icmp ugt <8 x i16> [[TMP10]], [[TMP11]] +// CHECK-NEXT: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP11:%.*]] = icmp sgt <4 x i32> [[TMP12]], [[TMP13]] +// CHECK-NEXT: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP13:%.*]] = icmp ugt <4 x i32> [[TMP14]], [[TMP15]] +// CHECK-NEXT: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP15:%.*]] = icmp ugt <4 x i32> [[TMP16]], [[TMP17]] +// CHECK-NEXT: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP17:%.*]] = icmp sgt <2 x i64> [[TMP18]], [[TMP19]] +// CHECK-NEXT: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP19:%.*]] = icmp ugt <2 x i64> [[TMP20]], [[TMP21]] +// CHECK-NEXT: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP21:%.*]] = icmp ugt <2 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[CMP23:%.*]] = fcmp ogt <2 x double> [[TMP24]], [[TMP25]] +// CHECK-NEXT: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_cmpgt(void) { bc = sc > sc2; @@ -3192,73 +3289,76 @@ void test_cmpgt(void) { bl = fd > fd2; } -// CHECK-LABEL: define{{.*}} void @test_cmple() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP:%.*]] = icmp sle <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP1:%.*]] = icmp ule <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP3:%.*]] = icmp ule <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP5:%.*]] = icmp sle <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP7:%.*]] = icmp ule <8 x i16> [[TMP8]], [[TMP9]] -// CHECK: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP9:%.*]] = icmp ule <8 x i16> [[TMP10]], [[TMP11]] -// CHECK: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP11:%.*]] = icmp sle <4 x i32> [[TMP12]], [[TMP13]] -// CHECK: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP13:%.*]] = icmp ule <4 x i32> [[TMP14]], [[TMP15]] -// CHECK: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP15:%.*]] = icmp ule <4 x i32> [[TMP16]], [[TMP17]] -// CHECK: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP17:%.*]] = icmp sle <2 x i64> [[TMP18]], [[TMP19]] -// CHECK: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP19:%.*]] = icmp ule <2 x i64> [[TMP20]], [[TMP21]] -// CHECK: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP21:%.*]] = icmp ule <2 x i64> [[TMP22]], [[TMP23]] -// CHECK: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[CMP23:%.*]] = fcmp ole <2 x double> [[TMP24]], [[TMP25]] -// CHECK: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_cmple( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp sle <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP1:%.*]] = icmp ule <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP3:%.*]] = icmp ule <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP5:%.*]] = icmp sle <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP7:%.*]] = icmp ule <8 x i16> [[TMP8]], [[TMP9]] +// CHECK-NEXT: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP9:%.*]] = icmp ule <8 x i16> [[TMP10]], [[TMP11]] +// CHECK-NEXT: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP11:%.*]] = icmp sle <4 x i32> [[TMP12]], [[TMP13]] +// CHECK-NEXT: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP13:%.*]] = icmp ule <4 x i32> [[TMP14]], [[TMP15]] +// CHECK-NEXT: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP15:%.*]] = icmp ule <4 x i32> [[TMP16]], [[TMP17]] +// CHECK-NEXT: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP17:%.*]] = icmp sle <2 x i64> [[TMP18]], [[TMP19]] +// CHECK-NEXT: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP19:%.*]] = icmp ule <2 x i64> [[TMP20]], [[TMP21]] +// CHECK-NEXT: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP21:%.*]] = icmp ule <2 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[CMP23:%.*]] = fcmp ole <2 x double> [[TMP24]], [[TMP25]] +// CHECK-NEXT: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_cmple(void) { bc = sc <= sc2; @@ -3280,73 +3380,76 @@ void test_cmple(void) { bl = fd <= fd2; } -// CHECK-LABEL: define{{.*}} void @test_cmplt() #0 { -// CHECK: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 -// CHECK: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 -// CHECK: [[CMP:%.*]] = icmp slt <16 x i8> [[TMP0]], [[TMP1]] -// CHECK: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 -// CHECK: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 -// CHECK: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 -// CHECK: [[CMP1:%.*]] = icmp ult <16 x i8> [[TMP2]], [[TMP3]] -// CHECK: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 -// CHECK: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 -// CHECK: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 -// CHECK: [[CMP3:%.*]] = icmp ult <16 x i8> [[TMP4]], [[TMP5]] -// CHECK: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> -// CHECK: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 -// CHECK: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 -// CHECK: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 -// CHECK: [[CMP5:%.*]] = icmp slt <8 x i16> [[TMP6]], [[TMP7]] -// CHECK: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 -// CHECK: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 -// CHECK: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 -// CHECK: [[CMP7:%.*]] = icmp ult <8 x i16> [[TMP8]], [[TMP9]] -// CHECK: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 -// CHECK: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 -// CHECK: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 -// CHECK: [[CMP9:%.*]] = icmp ult <8 x i16> [[TMP10]], [[TMP11]] -// CHECK: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> -// CHECK: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 -// CHECK: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 -// CHECK: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 -// CHECK: [[CMP11:%.*]] = icmp slt <4 x i32> [[TMP12]], [[TMP13]] -// CHECK: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 -// CHECK: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 -// CHECK: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 -// CHECK: [[CMP13:%.*]] = icmp ult <4 x i32> [[TMP14]], [[TMP15]] -// CHECK: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 -// CHECK: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 -// CHECK: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 -// CHECK: [[CMP15:%.*]] = icmp ult <4 x i32> [[TMP16]], [[TMP17]] -// CHECK: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> -// CHECK: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 -// CHECK: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 -// CHECK: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 -// CHECK: [[CMP17:%.*]] = icmp slt <2 x i64> [[TMP18]], [[TMP19]] -// CHECK: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 -// CHECK: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 -// CHECK: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 -// CHECK: [[CMP19:%.*]] = icmp ult <2 x i64> [[TMP20]], [[TMP21]] -// CHECK: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 -// CHECK: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 -// CHECK: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 -// CHECK: [[CMP21:%.*]] = icmp ult <2 x i64> [[TMP22]], [[TMP23]] -// CHECK: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 -// CHECK: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 -// CHECK: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 -// CHECK: [[CMP23:%.*]] = fcmp olt <2 x double> [[TMP24]], [[TMP25]] -// CHECK: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> -// CHECK: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 -// CHECK: ret void +// CHECK-LABEL: define dso_local void @test_cmplt( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <16 x i8>, ptr @sc, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <16 x i8>, ptr @sc2, align 8 +// CHECK-NEXT: [[CMP:%.*]] = icmp slt <16 x i8> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <16 x i1> [[CMP]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load volatile <16 x i8>, ptr @uc, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = load volatile <16 x i8>, ptr @uc2, align 8 +// CHECK-NEXT: [[CMP1:%.*]] = icmp ult <16 x i8> [[TMP2]], [[TMP3]] +// CHECK-NEXT: [[SEXT2:%.*]] = sext <16 x i1> [[CMP1]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT2]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load volatile <16 x i8>, ptr @bc, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = load volatile <16 x i8>, ptr @bc2, align 8 +// CHECK-NEXT: [[CMP3:%.*]] = icmp ult <16 x i8> [[TMP4]], [[TMP5]] +// CHECK-NEXT: [[SEXT4:%.*]] = sext <16 x i1> [[CMP3]] to <16 x i8> +// CHECK-NEXT: store volatile <16 x i8> [[SEXT4]], ptr @bc, align 8 +// CHECK-NEXT: [[TMP6:%.*]] = load volatile <8 x i16>, ptr @ss, align 8 +// CHECK-NEXT: [[TMP7:%.*]] = load volatile <8 x i16>, ptr @ss2, align 8 +// CHECK-NEXT: [[CMP5:%.*]] = icmp slt <8 x i16> [[TMP6]], [[TMP7]] +// CHECK-NEXT: [[SEXT6:%.*]] = sext <8 x i1> [[CMP5]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT6]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP8:%.*]] = load volatile <8 x i16>, ptr @us, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = load volatile <8 x i16>, ptr @us2, align 8 +// CHECK-NEXT: [[CMP7:%.*]] = icmp ult <8 x i16> [[TMP8]], [[TMP9]] +// CHECK-NEXT: [[SEXT8:%.*]] = sext <8 x i1> [[CMP7]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT8]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP10:%.*]] = load volatile <8 x i16>, ptr @bs, align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load volatile <8 x i16>, ptr @bs2, align 8 +// CHECK-NEXT: [[CMP9:%.*]] = icmp ult <8 x i16> [[TMP10]], [[TMP11]] +// CHECK-NEXT: [[SEXT10:%.*]] = sext <8 x i1> [[CMP9]] to <8 x i16> +// CHECK-NEXT: store volatile <8 x i16> [[SEXT10]], ptr @bs, align 8 +// CHECK-NEXT: [[TMP12:%.*]] = load volatile <4 x i32>, ptr @si, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = load volatile <4 x i32>, ptr @si2, align 8 +// CHECK-NEXT: [[CMP11:%.*]] = icmp slt <4 x i32> [[TMP12]], [[TMP13]] +// CHECK-NEXT: [[SEXT12:%.*]] = sext <4 x i1> [[CMP11]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT12]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP14:%.*]] = load volatile <4 x i32>, ptr @ui, align 8 +// CHECK-NEXT: [[TMP15:%.*]] = load volatile <4 x i32>, ptr @ui2, align 8 +// CHECK-NEXT: [[CMP13:%.*]] = icmp ult <4 x i32> [[TMP14]], [[TMP15]] +// CHECK-NEXT: [[SEXT14:%.*]] = sext <4 x i1> [[CMP13]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT14]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load volatile <4 x i32>, ptr @bi, align 8 +// CHECK-NEXT: [[TMP17:%.*]] = load volatile <4 x i32>, ptr @bi2, align 8 +// CHECK-NEXT: [[CMP15:%.*]] = icmp ult <4 x i32> [[TMP16]], [[TMP17]] +// CHECK-NEXT: [[SEXT16:%.*]] = sext <4 x i1> [[CMP15]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT16]], ptr @bi, align 8 +// CHECK-NEXT: [[TMP18:%.*]] = load volatile <2 x i64>, ptr @sl, align 8 +// CHECK-NEXT: [[TMP19:%.*]] = load volatile <2 x i64>, ptr @sl2, align 8 +// CHECK-NEXT: [[CMP17:%.*]] = icmp slt <2 x i64> [[TMP18]], [[TMP19]] +// CHECK-NEXT: [[SEXT18:%.*]] = sext <2 x i1> [[CMP17]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT18]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP20:%.*]] = load volatile <2 x i64>, ptr @ul, align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load volatile <2 x i64>, ptr @ul2, align 8 +// CHECK-NEXT: [[CMP19:%.*]] = icmp ult <2 x i64> [[TMP20]], [[TMP21]] +// CHECK-NEXT: [[SEXT20:%.*]] = sext <2 x i1> [[CMP19]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT20]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP22:%.*]] = load volatile <2 x i64>, ptr @bl, align 8 +// CHECK-NEXT: [[TMP23:%.*]] = load volatile <2 x i64>, ptr @bl2, align 8 +// CHECK-NEXT: [[CMP21:%.*]] = icmp ult <2 x i64> [[TMP22]], [[TMP23]] +// CHECK-NEXT: [[SEXT22:%.*]] = sext <2 x i1> [[CMP21]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT22]], ptr @bl, align 8 +// CHECK-NEXT: [[TMP24:%.*]] = load volatile <2 x double>, ptr @fd, align 8 +// CHECK-NEXT: [[TMP25:%.*]] = load volatile <2 x double>, ptr @fd2, align 8 +// CHECK-NEXT: [[CMP23:%.*]] = fcmp olt <2 x double> [[TMP24]], [[TMP25]] +// CHECK-NEXT: [[SEXT24:%.*]] = sext <2 x i1> [[CMP23]] to <2 x i64> +// CHECK-NEXT: store volatile <2 x i64> [[SEXT24]], ptr @bl, align 8 +// CHECK-NEXT: ret void +// void test_cmplt(void) { bc = sc < sc2; diff --git a/clang/test/CodeGen/SystemZ/zvector2.c b/clang/test/CodeGen/SystemZ/zvector2.c index 5b036433519bdd2be7a1e7c2f579f1f6a1dd5c76..b021ae8534353688d9f5166913da34467af3d28e 100644 --- a/clang/test/CodeGen/SystemZ/zvector2.c +++ b/clang/test/CodeGen/SystemZ/zvector2.c @@ -1,194 +1,303 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 // RUN: %clang_cc1 -triple s390x-linux-gnu -target-cpu z14 -fzvector \ // RUN: -O -emit-llvm -o - -W -Wall -Werror %s | FileCheck %s volatile vector float ff, ff2; volatile vector bool int bi; +// CHECK-LABEL: define dso_local void @test_assign( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3:![0-9]+]] +// CHECK-NEXT: store volatile <4 x float> [[TMP0]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_assign (void) { -// CHECK-LABEL: test_assign -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: store volatile <4 x float> [[VAL]], ptr @ff ff = ff2; } +// CHECK-LABEL: define dso_local void @test_pos( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: store volatile <4 x float> [[TMP0]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_pos (void) { -// CHECK-LABEL: test_pos -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: store volatile <4 x float> [[VAL]], ptr @ff ff = +ff2; } +// CHECK-LABEL: define dso_local void @test_neg( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[FNEG:%.*]] = fneg <4 x float> [[TMP0]] +// CHECK-NEXT: store volatile <4 x float> [[FNEG]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_neg (void) { -// CHECK-LABEL: test_neg -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fneg <4 x float> [[VAL]] ff = -ff2; } +// CHECK-LABEL: define dso_local void @test_preinc( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[INC:%.*]] = fadd <4 x float> [[TMP0]], splat (float 1.000000e+00) +// CHECK-NEXT: store volatile <4 x float> [[INC]], ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_preinc (void) { -// CHECK-LABEL: test_preinc -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fadd <4 x float> [[VAL]], splat (float 1.000000e+00) ++ff2; } +// CHECK-LABEL: define dso_local void @test_postinc( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[INC:%.*]] = fadd <4 x float> [[TMP0]], splat (float 1.000000e+00) +// CHECK-NEXT: store volatile <4 x float> [[INC]], ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_postinc (void) { -// CHECK-LABEL: test_postinc -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fadd <4 x float> [[VAL]], splat (float 1.000000e+00) ff2++; } +// CHECK-LABEL: define dso_local void @test_predec( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[DEC:%.*]] = fadd <4 x float> [[TMP0]], splat (float -1.000000e+00) +// CHECK-NEXT: store volatile <4 x float> [[DEC]], ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_predec (void) { -// CHECK-LABEL: test_predec -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fadd <4 x float> [[VAL]], splat (float -1.000000e+00) --ff2; } +// CHECK-LABEL: define dso_local void @test_postdec( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[DEC:%.*]] = fadd <4 x float> [[TMP0]], splat (float -1.000000e+00) +// CHECK-NEXT: store volatile <4 x float> [[DEC]], ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_postdec (void) { -// CHECK-LABEL: test_postdec -// CHECK: [[VAL:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fadd <4 x float> [[VAL]], splat (float -1.000000e+00) ff2--; } +// CHECK-LABEL: define dso_local void @test_add( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[ADD:%.*]] = fadd <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <4 x float> [[ADD]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_add (void) { -// CHECK-LABEL: test_add -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fadd <4 x float> [[VAL1]], [[VAL2]] ff = ff + ff2; } +// CHECK-LABEL: define dso_local void @test_add_assign( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[ADD:%.*]] = fadd <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <4 x float> [[ADD]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_add_assign (void) { -// CHECK-LABEL: test_add_assign -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: %{{.*}} = fadd <4 x float> [[VAL2]], [[VAL1]] ff += ff2; } +// CHECK-LABEL: define dso_local void @test_sub( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[SUB:%.*]] = fsub <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <4 x float> [[SUB]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_sub (void) { -// CHECK-LABEL: test_sub -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fsub <4 x float> [[VAL1]], [[VAL2]] ff = ff - ff2; } +// CHECK-LABEL: define dso_local void @test_sub_assign( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[SUB:%.*]] = fsub <4 x float> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <4 x float> [[SUB]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_sub_assign (void) { -// CHECK-LABEL: test_sub_assign -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: %{{.*}} = fsub <4 x float> [[VAL1]], [[VAL2]] ff -= ff2; } +// CHECK-LABEL: define dso_local void @test_mul( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[MUL:%.*]] = fmul <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <4 x float> [[MUL]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_mul (void) { -// CHECK-LABEL: test_mul -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fmul <4 x float> [[VAL1]], [[VAL2]] ff = ff * ff2; } +// CHECK-LABEL: define dso_local void @test_mul_assign( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[MUL:%.*]] = fmul <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <4 x float> [[MUL]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_mul_assign (void) { -// CHECK-LABEL: test_mul_assign -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: %{{.*}} = fmul <4 x float> [[VAL2]], [[VAL1]] ff *= ff2; } +// CHECK-LABEL: define dso_local void @test_div( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[DIV:%.*]] = fdiv <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: store volatile <4 x float> [[DIV]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_div (void) { -// CHECK-LABEL: test_div -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: %{{.*}} = fdiv <4 x float> [[VAL1]], [[VAL2]] ff = ff / ff2; } +// CHECK-LABEL: define dso_local void @test_div_assign( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[DIV:%.*]] = fdiv <4 x float> [[TMP1]], [[TMP0]] +// CHECK-NEXT: store volatile <4 x float> [[DIV]], ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_div_assign (void) { -// CHECK-LABEL: test_div_assign -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: %{{.*}} = fdiv <4 x float> [[VAL1]], [[VAL2]] ff /= ff2; } +// CHECK-LABEL: define dso_local void @test_cmpeq( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT]], ptr @bi, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_cmpeq (void) { -// CHECK-LABEL: test_cmpeq -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[CMP:%[^ ]+]] = fcmp oeq <4 x float> [[VAL1]], [[VAL2]] -// CHECK: %{{.*}} = sext <4 x i1> [[CMP]] to <4 x i32> bi = ff == ff2; } +// CHECK-LABEL: define dso_local void @test_cmpne( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[CMP:%.*]] = fcmp une <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT]], ptr @bi, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_cmpne (void) { -// CHECK-LABEL: test_cmpne -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[CMP:%[^ ]+]] = fcmp une <4 x float> [[VAL1]], [[VAL2]] -// CHECK: %{{.*}} = sext <4 x i1> [[CMP]] to <4 x i32> bi = ff != ff2; } +// CHECK-LABEL: define dso_local void @test_cmpge( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[CMP:%.*]] = fcmp oge <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT]], ptr @bi, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_cmpge (void) { -// CHECK-LABEL: test_cmpge -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[CMP:%[^ ]+]] = fcmp oge <4 x float> [[VAL1]], [[VAL2]] -// CHECK: %{{.*}} = sext <4 x i1> [[CMP]] to <4 x i32> bi = ff >= ff2; } +// CHECK-LABEL: define dso_local void @test_cmpgt( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT]], ptr @bi, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_cmpgt (void) { -// CHECK-LABEL: test_cmpgt -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[CMP:%[^ ]+]] = fcmp ogt <4 x float> [[VAL1]], [[VAL2]] -// CHECK: %{{.*}} = sext <4 x i1> [[CMP]] to <4 x i32> bi = ff > ff2; } +// CHECK-LABEL: define dso_local void @test_cmple( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[CMP:%.*]] = fcmp ole <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT]], ptr @bi, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_cmple (void) { -// CHECK-LABEL: test_cmple -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[CMP:%[^ ]+]] = fcmp ole <4 x float> [[VAL1]], [[VAL2]] -// CHECK: %{{.*}} = sext <4 x i1> [[CMP]] to <4 x i32> bi = ff <= ff2; } +// CHECK-LABEL: define dso_local void @test_cmplt( +// CHECK-SAME: ) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[TMP0:%.*]] = load volatile <4 x float>, ptr @ff, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[TMP1:%.*]] = load volatile <4 x float>, ptr @ff2, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <4 x float> [[TMP0]], [[TMP1]] +// CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[CMP]] to <4 x i32> +// CHECK-NEXT: store volatile <4 x i32> [[SEXT]], ptr @bi, align 8, !tbaa [[TBAA3]] +// CHECK-NEXT: ret void +// void test_cmplt (void) { -// CHECK-LABEL: test_cmplt -// CHECK: [[VAL1:%[^ ]+]] = load volatile <4 x float>, ptr @ff -// CHECK: [[VAL2:%[^ ]+]] = load volatile <4 x float>, ptr @ff2 -// CHECK: [[CMP:%[^ ]+]] = fcmp olt <4 x float> [[VAL1]], [[VAL2]] -// CHECK: %{{.*}} = sext <4 x i1> [[CMP]] to <4 x i32> bi = ff < ff2; } +//. +// CHECK: [[TBAA3]] = !{[[META4:![0-9]+]], [[META4]], i64 0} +// CHECK: [[META4]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0} +// CHECK: [[META5]] = !{!"Simple C/C++ TBAA"} +//. diff --git a/clang/test/CodeGen/X86/amx_fp8_api.c b/clang/test/CodeGen/X86/amx_fp8_api.c new file mode 100644 index 0000000000000000000000000000000000000000..2a3af1b7f5cd9ab93126709582c26e3739b83e40 --- /dev/null +++ b/clang/test/CodeGen/X86/amx_fp8_api.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +amx-fp8 \ +// RUN: -emit-llvm -o - -Werror -pedantic | FileCheck %s +#include + +void test_tdpbf8ps(__tile1024i src1, __tile1024i src2, __tile1024i dst) { + //CHECK-LABEL: @test_tdpbf8ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.tdpbf8ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_dpbf8ps(&dst, src1, src2); +} + +void test_tdpbhf8ps(__tile1024i src1, __tile1024i src2, __tile1024i dst) { + //CHECK-LABEL: @test_tdpbhf8ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.tdpbhf8ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_dpbhf8ps(&dst, src1, src2); +} + +void test_tdphbf8ps(__tile1024i src1, __tile1024i src2, __tile1024i dst) { + //CHECK-LABEL: @test_tdphbf8ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.tdphbf8ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_dphbf8ps(&dst, src1, src2); +} + +void test_tdphf8ps(__tile1024i src1, __tile1024i src2, __tile1024i dst) { + //CHECK-LABEL: @test_tdphf8ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.tdphf8ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_dphf8ps(&dst, src1, src2); +} + diff --git a/clang/test/CodeGen/X86/amx_transpose.c b/clang/test/CodeGen/X86/amx_transpose.c index deefc592c7ae6674f3e6f014e1e94101aa837598..7e88fd80592d62cc65554d684c4b1278e8a048de 100644 --- a/clang/test/CodeGen/X86/amx_transpose.c +++ b/clang/test/CodeGen/X86/amx_transpose.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown -target-feature +amx-transpose \ +// RUN: -target-feature +amx-bf16 -target-feature +amx-fp16 -target-feature +amx-complex \ // RUN: -target-feature +avx512f -emit-llvm -o - -Wall -Werror -pedantic -Wno-gnu-statement-expression| FileCheck %s #include @@ -34,3 +35,41 @@ void test_tile_transposed(void) // CHECK: call void @llvm.x86.ttransposed(i8 1, i8 2) _tile_transposed(1, 2); } + +void test_tile_tdpbf16ps(void) +{ + // CHECK-LABEL: @test_tile_tdpbf16ps + // CHECK: call void @llvm.x86.ttdpbf16ps(i8 1, i8 2, i8 3) + _tile_tdpbf16ps(1, 2, 3); +} + +void test_tile_tdpfp16ps(void) +{ + // CHECK-LABEL: @test_tile_tdpfp16ps + // CHECK: call void @llvm.x86.ttdpfp16ps(i8 4, i8 5, i8 6) + _tile_tdpfp16ps(4, 5, 6); +} + +void test_tile_tcmmimfp16ps(void) { + // CHECK-LABEL: @test_tile_tcmmimfp16ps + // CHECK: call void @llvm.x86.ttcmmimfp16ps(i8 1, i8 2, i8 3) + _tile_tcmmimfp16ps(1, 2, 3); +} + +void test_tile_tcmmrlfp16ps(void) { + // CHECK-LABEL: @test_tile_tcmmrlfp16ps + // CHECK: call void @llvm.x86.ttcmmrlfp16ps(i8 1, i8 2, i8 3) + _tile_tcmmrlfp16ps(1, 2, 3); +} + +void test_tile_conjtcmmimfp16ps(void) { + // CHECK-LABEL: @test_tile_conjtcmmimfp16ps + // CHECK: call void @llvm.x86.tconjtcmmimfp16ps(i8 1, i8 2, i8 3) + _tile_conjtcmmimfp16ps(1, 2, 3); +} + +void test_tile_conjtfp16(void) { + // CHECK-LABEL: @test_tile_conjtfp16 + // CHECK: call void @llvm.x86.tconjtfp16(i8 1, i8 2) + _tile_conjtfp16(1, 2); +} diff --git a/clang/test/CodeGen/X86/amx_transpose_api.c b/clang/test/CodeGen/X86/amx_transpose_api.c index 10310c2332b7a62e08cc61d235464709a0bd8c61..dc3ef5104252ca3048d2d2ca7cc8c5a4e7aba52f 100644 --- a/clang/test/CodeGen/X86/amx_transpose_api.c +++ b/clang/test/CodeGen/X86/amx_transpose_api.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -flax-vector-conversions=none -ffreestanding -triple=x86_64-unknown-unknown -target-feature +avx512f \ -// RUN: -target-feature +amx-transpose \ +// RUN: -target-feature +amx-transpose -target-feature +amx-bf16 -target-feature +amx-fp16 -target-feature +amx-complex \ // RUN: -emit-llvm -o - -Werror -pedantic | FileCheck %s --check-prefixes=CHECK #include @@ -64,3 +64,51 @@ void test_tile_transposed(__tile1024i dst, __tile1024i src) { //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) __tile_transposed(&dst, src); } + +void test_tile_tdpbf16ps(__tile1024i a, __tile1024i b, __tile1024i c) { + //CHECK-LABEL: @test_tile_tdpbf16ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.ttdpbf16ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_tdpbf16ps(&c, a, b); +} + +void test_tile_tdpfp16ps(__tile1024i a, __tile1024i b, __tile1024i c) { + //CHECK-LABEL: @test_tile_tdpfp16ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.ttdpfp16ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_tdpfp16ps(&c, a, b); +} + +void test_tile_tcmmimfp16ps(__tile1024i a, __tile1024i b, __tile1024i c) { + //CHECK-LABEL: @test_tile_tcmmimfp16ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.ttcmmimfp16ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_tcmmimfp16ps(&c, a, b); +} + +void test_tile_tcmmrlfp16ps(__tile1024i a, __tile1024i b, __tile1024i c) { + //CHECK-LABEL: @test_tile_tcmmrlfp16ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.ttcmmrlfp16ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_tcmmrlfp16ps(&c, a, b); +} + +void test_tile_conjtcmmimfp16ps(__tile1024i a, __tile1024i b, __tile1024i c) { + //CHECK-LABEL: @test_tile_conjtcmmimfp16ps + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.tconjtcmmimfp16ps.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_conjtcmmimfp16ps(&c, a, b); +} + +void test_tile_conjtfp16(__tile1024i dst, __tile1024i src) { + //CHECK-LABEL: @test_tile_conjtfp16 + //CHECK-DAG: call x86_amx @llvm.x86.cast.vector.to.tile.v256i32(<256 x i32> {{%.*}}) + //CHECK-DAG: call x86_amx @llvm.x86.tconjtfp16.internal + //CHECK-DAG: call <256 x i32> @llvm.x86.cast.tile.to.vector.v256i32(x86_amx {{%.*}}) + __tile_conjtfp16(&dst, src); +} diff --git a/clang/test/CodeGen/X86/amx_transpose_errors.c b/clang/test/CodeGen/X86/amx_transpose_errors.c index 80084c42a240dd601e2d07f3de40a883b5777c92..80368c580c793a70a2f16e26d1e996e521379753 100644 --- a/clang/test/CodeGen/X86/amx_transpose_errors.c +++ b/clang/test/CodeGen/X86/amx_transpose_errors.c @@ -1,9 +1,7 @@ // RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown \ // RUN: -target-feature +amx-int8 -target-feature +amx-bf16 -target-feature +amx-transpose \ -// RUN: -target-feature +avx512f -target-feature +amx-element-evex -verify +// RUN: -target-feature +avx512f -target-feature +amx-fp16 -target-feature +amx-complex -verify -#include -#include #include #include @@ -24,8 +22,54 @@ void test_tile_2rpntlvwz1t1(const void *A, size_t B) { _tile_2rpntlvwz1t1(8, A, B); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } +void test_tile_tdpbf16ps() +{ + _tile_tdpbf16ps(8, 2, 3); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + _tile_tdpbf16ps(1, 8, 3); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + _tile_tdpbf16ps(1, 2, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + _tile_tdpbf16ps(1, 1, 3); // expected-error {{tile arguments must refer to different tiles}} + _tile_tdpbf16ps(1, 2, 1); // expected-error {{tile arguments must refer to different tiles}} + _tile_tdpbf16ps(1, 2, 2); // expected-error {{tile arguments must refer to different tiles}} +} + +void test_tile_tdpfp16ps() +{ + _tile_tdpfp16ps(8, 5, 6); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + _tile_tdpfp16ps(1, 8, 6); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + _tile_tdpfp16ps(1, 5, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} + _tile_tdpfp16ps(1, 1, 3); // expected-error {{tile arguments must refer to different tiles}} + _tile_tdpfp16ps(1, 2, 1); // expected-error {{tile arguments must refer to different tiles}} + _tile_tdpfp16ps(1, 2, 2); // expected-error {{tile arguments must refer to different tiles}} +} + void test_tile_transposed() { _tile_transposed(8, 2); // expected-error {{argument value 8 is outside the valid range [0, 7]}} _tile_transposed(1, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} } + +void test_tile_tcmmimfp16ps() { + _tile_tcmmimfp16ps(16, 2, 3); // expected-error {{argument value 16 is outside the valid range [0, 7]}} + _tile_tcmmimfp16ps(1, 26, 3); // expected-error {{argument value 26 is outside the valid range [0, 7]}} + _tile_tcmmimfp16ps(1, 2, 36); // expected-error {{argument value 36 is outside the valid range [0, 7]}} + _tile_tcmmimfp16ps(1, 1, 3); // expected-error {{tile arguments must refer to different tiles}} +} + +void test_tile_tcmmrlfp16ps() { + _tile_tcmmrlfp16ps(16, 2, 3); // expected-error {{argument value 16 is outside the valid range [0, 7]}} + _tile_tcmmrlfp16ps(1, 26, 3); // expected-error {{argument value 26 is outside the valid range [0, 7]}} + _tile_tcmmrlfp16ps(1, 2, 36); // expected-error {{argument value 36 is outside the valid range [0, 7]}} + _tile_tcmmrlfp16ps(1, 1, 3); // expected-error {{tile arguments must refer to different tiles}} +} + +void test_tile_conjtcmmimfp16ps() { + _tile_conjtcmmimfp16ps(16, 2, 3); // expected-error {{argument value 16 is outside the valid range [0, 7]}} + _tile_conjtcmmimfp16ps(1, 26, 3); // expected-error {{argument value 26 is outside the valid range [0, 7]}} + _tile_conjtcmmimfp16ps(1, 2, 36); // expected-error {{argument value 36 is outside the valid range [0, 7]}} + _tile_conjtcmmimfp16ps(1, 2, 1); // expected-error {{tile arguments must refer to different tiles}} +} + +void test_tile_conjtfp16() { + _tile_conjtfp16(16, 2); // expected-error {{argument value 16 is outside the valid range [0, 7]}} + _tile_conjtfp16(1, 26); // expected-error {{argument value 26 is outside the valid range [0, 7]}} +} diff --git a/clang/test/CodeGen/X86/math-builtins.c b/clang/test/CodeGen/X86/math-builtins.c index 48465df21cca19a21a068398ee87d90ec5e4345b..bf107437fc63a32c2b9d8892d6a4b66832693636 100644 --- a/clang/test/CodeGen/X86/math-builtins.c +++ b/clang/test/CodeGen/X86/math-builtins.c @@ -45,10 +45,10 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_atan2(f,f); __builtin_atan2f(f,f) ; __builtin_atan2l(f, f); __builtin_atan2f128(f,f); -// NO__ERRNO: declare double @atan2(double noundef, double noundef) [[READNONE:#[0-9]+]] -// NO__ERRNO: declare float @atan2f(float noundef, float noundef) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[READNONE]] -// NO__ERRNO: declare fp128 @atan2f128(fp128 noundef, fp128 noundef) [[READNONE]] +// NO__ERRNO: declare double @llvm.atan2.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// NO__ERRNO: declare float @llvm.atan2.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.atan2.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare fp128 @llvm.atan2.f128(fp128, fp128) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @atan2(double noundef, double noundef) [[NOT_READNONE]] // HAS_ERRNO: declare float @atan2f(float noundef, float noundef) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]] @@ -56,7 +56,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_copysign(f,f); __builtin_copysignf(f,f); __builtin_copysignl(f,f); __builtin_copysignf128(f,f); -// NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] // NO__ERRNO: declare fp128 @llvm.copysign.f128(fp128, fp128) [[READNONE_INTRINSIC]] @@ -179,7 +179,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_acosh(f); __builtin_acoshf(f); __builtin_acoshl(f); __builtin_acoshf128(f); -// NO__ERRNO: declare double @acosh(double noundef) [[READNONE]] +// NO__ERRNO: declare double @acosh(double noundef) [[READNONE:#[0-9]+]] // NO__ERRNO: declare float @acoshf(float noundef) [[READNONE]] // NO__ERRNO: declare x86_fp80 @acoshl(x86_fp80 noundef) [[READNONE]] // NO__ERRNO: declare fp128 @acoshf128(fp128 noundef) [[READNONE]] @@ -721,10 +721,10 @@ __builtin_trunc(f); __builtin_truncf(f); __builtin_truncl(f); __builtin // HAS_ERRNO: declare fp128 @llvm.trunc.f128(fp128) [[READNONE_INTRINSIC]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // NO__ERRNO: attributes [[PURE]] = { {{.*}}memory(read){{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } diff --git a/clang/test/CodeGen/X86/movrs-builtins.c b/clang/test/CodeGen/X86/movrs-builtins.c new file mode 100644 index 0000000000000000000000000000000000000000..c428cd99af349cf92ad96c484524bf19c6d3344a --- /dev/null +++ b/clang/test/CodeGen/X86/movrs-builtins.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -flax-vector-conversions=none -ffreestanding -triple=x86_64-unknown-unknown -target-feature +movrs \ +// RUN: -emit-llvm -o - -Wall -Werror -pedantic -Wno-gnu-statement-expression | FileCheck %s + +#include +#include + +char test_movrs_si8(const char * __A) { + // CHECK-LABEL: @test_movrs_si8( + // CHECK: call i8 @llvm.x86.movrsqi( + return _movrs_i8(__A); +} + +short test_movrs_si16(const short * __A) { + // CHECK-LABEL: @test_movrs_si16( + // CHECK: call i16 @llvm.x86.movrshi( + return _movrs_i16(__A); +} + +int test_movrs_si32(const int * __A) { + // CHECK-LABEL: @test_movrs_si32( + // CHECK: call i32 @llvm.x86.movrssi( + return _movrs_i32(__A); +} + +long long test_movrs_si64(const long long * __A) { + // CHECK-LABEL: @test_movrs_si64( + // CHECK: call i64 @llvm.x86.movrsdi( + return _movrs_i64(__A); +} + +void test_m_prefetch_rs(void *p) { + _m_prefetchrs(p); + // CHECK-LABEL: define{{.*}} void @test_m_prefetch_rs + // CHECK: call void @llvm.x86.prefetchrs({{.*}}) +} diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c index b90e2679e26d27d0a0bb4e056943da6cdcc97c66..94a1b372974b38fb0e1537d481b0604f9c299ab2 100644 --- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c +++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c @@ -171,7 +171,7 @@ __int64 test_mul128(__int64 Multiplier, __int64 *HighProduct) { return _mul128(Multiplier, Multiplicand, HighProduct); } -// CHECK-X64-LABEL: define dso_local i64 @test_mul128(i64 noundef %Multiplier, i64 noundef %Multiplicand, ptr{{[a-z_ ]*}}%HighProduct) +// CHECK-X64-LABEL: define dso_local i64 @test_mul128(i64 noundef %Multiplier, i64 noundef %Multiplicand, ptr{{[a-z_ ]*}} initializes((0, 8)) %HighProduct) // CHECK-X64: = sext i64 %Multiplier to i128 // CHECK-X64: = sext i64 %Multiplicand to i128 // CHECK-X64: = mul nsw i128 % @@ -183,7 +183,7 @@ unsigned __int64 test_umul128(unsigned __int64 Multiplier, unsigned __int64 *HighProduct) { return _umul128(Multiplier, Multiplicand, HighProduct); } -// CHECK-X64-LABEL: define dso_local i64 @test_umul128(i64 noundef %Multiplier, i64 noundef %Multiplicand, ptr{{[a-z_ ]*}}%HighProduct) +// CHECK-X64-LABEL: define dso_local i64 @test_umul128(i64 noundef %Multiplier, i64 noundef %Multiplicand, ptr{{[a-z_ ]*}} initializes((0, 8)) %HighProduct) // CHECK-X64: = zext i64 %Multiplier to i128 // CHECK-X64: = zext i64 %Multiplicand to i128 // CHECK-X64: = mul nuw i128 % diff --git a/clang/test/CodeGen/X86/x86_64-PR42672.c b/clang/test/CodeGen/X86/x86_64-PR42672.c index 6fe612d0aabdbf31e0d662faad4dd0bffd9c213b..42894c0c4cb570203e39fb750b8e9c959944868a 100644 --- a/clang/test/CodeGen/X86/x86_64-PR42672.c +++ b/clang/test/CodeGen/X86/x86_64-PR42672.c @@ -58,7 +58,7 @@ void odd_struct(void) { : "=r"(str)); #endif } -// CHECK-IMPOSSIBLE_ODD: impossible constraint in asm: can't store value into a register +// CHECK-IMPOSSIBLE_ODD: impossible constraint in asm: cannot store value into a register // Check Clang reports an error if attempting to return a big structure via a register. void big_struct(void) { @@ -70,7 +70,7 @@ void big_struct(void) { : "=r"(str)); #endif } -// CHECK-IMPOSSIBLE_BIG: impossible constraint in asm: can't store value into a register +// CHECK-IMPOSSIBLE_BIG: impossible constraint in asm: cannot store value into a register // Clang is able to emit LLVM IR for an 16-byte structure. void x_constraint_fit(void) { @@ -103,7 +103,7 @@ void x_constraint_nofit(void) { // http://crbug.com/999160 // Clang used to report the following message: -// "impossible constraint in asm: can't store struct into a register" +// "impossible constraint in asm: cannot store struct into a register" // for the assembly directive below, although there's no struct. void crbug_999160_regtest(void) { #ifdef IMPOSSIBLE_9BYTES @@ -113,7 +113,7 @@ void crbug_999160_regtest(void) { #endif } -// CHECK-IMPOSSIBLE_9BYTES: impossible constraint in asm: can't store value into a register +// CHECK-IMPOSSIBLE_9BYTES: impossible constraint in asm: cannot store value into a register void crbug_999160_regtest_v2(void) { #ifdef IMPOSSIBLE_9BYTES_V2 @@ -121,4 +121,4 @@ void crbug_999160_regtest_v2(void) { asm("" : "=r"(buf) : "0"(buf)); #endif } -// CHECK-IMPOSSIBLE_9BYTES_V2: impossible constraint in asm: can't store value into a register +// CHECK-IMPOSSIBLE_9BYTES_V2: impossible constraint in asm: cannot store value into a register diff --git a/clang/test/CodeGen/aarch64-debug-types.c b/clang/test/CodeGen/aarch64-debug-types.c deleted file mode 100644 index f1ab74c5c31bdb1ca9e6d96d0ca31cad6562b7ce..0000000000000000000000000000000000000000 --- a/clang/test/CodeGen/aarch64-debug-types.c +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon -target-feature +fp8 \ -// RUN: -emit-llvm -o - %s -debug-info-kind=limited 2>&1 | FileCheck %s - -// REQUIRES: aarch64-registered-target - -#include - -void test_locals(void) { - // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "__MFloat8_t", {{.*}}, baseType: ![[ELTTYU8:[0-9]+]] - // CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "__MFloat8_t", size: 8, encoding: DW_ATE_unsigned_char) - __MFloat8_t mfp8; -} diff --git a/clang/test/CodeGen/aarch64-fmv-streaming.c b/clang/test/CodeGen/aarch64-fmv-streaming.c deleted file mode 100644 index e549ccda59ad888f11745ab26eba8b18726666a0..0000000000000000000000000000000000000000 --- a/clang/test/CodeGen/aarch64-fmv-streaming.c +++ /dev/null @@ -1,107 +0,0 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -emit-llvm -o - %s | FileCheck %s - - -// CHECK-LABEL: define {{[^@]+}}@n_callee._Msve -// CHECK-SAME: () #[[ATTR0:[0-9]+]] { -// -// CHECK-LABEL: define {{[^@]+}}@n_callee._Msimd -// CHECK-SAME: () #[[ATTR1:[0-9]+]] { -// -__arm_locally_streaming __attribute__((target_clones("sve", "simd"))) void n_callee(void) {} -// CHECK-LABEL: define {{[^@]+}}@n_callee._Msme2 -// CHECK-SAME: () #[[ATTR2:[0-9]+]] { -// -__attribute__((target_version("sme2"))) void n_callee(void) {} -// CHECK-LABEL: define {{[^@]+}}@n_callee.default -// CHECK-SAME: () #[[ATTR3:[0-9]+]] { -// -__attribute__((target_version("default"))) void n_callee(void) {} - - -// CHECK-LABEL: define {{[^@]+}}@s_callee._Msve -// CHECK-SAME: () #[[ATTR4:[0-9]+]] { -// -// CHECK-LABEL: define {{[^@]+}}@s_callee._Msimd -// CHECK-SAME: () #[[ATTR5:[0-9]+]] { -// -__attribute__((target_clones("sve", "simd"))) void s_callee(void) __arm_streaming {} -// CHECK-LABEL: define {{[^@]+}}@s_callee._Msme2 -// CHECK-SAME: () #[[ATTR6:[0-9]+]] { -// -__arm_locally_streaming __attribute__((target_version("sme2"))) void s_callee(void) __arm_streaming {} -// CHECK-LABEL: define {{[^@]+}}@s_callee.default -// CHECK-SAME: () #[[ATTR7:[0-9]+]] { -// -__attribute__((target_version("default"))) void s_callee(void) __arm_streaming {} - - -// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msve -// CHECK-SAME: () #[[ATTR8:[0-9]+]] { -// -// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msimd -// CHECK-SAME: () #[[ATTR9:[0-9]+]] { -// -__attribute__((target_clones("sve", "simd"))) void sc_callee(void) __arm_streaming_compatible {} -// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msme2 -// CHECK-SAME: () #[[ATTR10:[0-9]+]] { -// -__arm_locally_streaming __attribute__((target_version("sme2"))) void sc_callee(void) __arm_streaming_compatible {} -// CHECK-LABEL: define {{[^@]+}}@sc_callee.default -// CHECK-SAME: () #[[ATTR11:[0-9]+]] { -// -__attribute__((target_version("default"))) void sc_callee(void) __arm_streaming_compatible {} - - -// CHECK-LABEL: define {{[^@]+}}@n_caller -// CHECK-SAME: () #[[ATTR3:[0-9]+]] { -// CHECK: call void @n_callee() -// CHECK: call void @s_callee() #[[ATTR12:[0-9]+]] -// CHECK: call void @sc_callee() #[[ATTR13:[0-9]+]] -// -void n_caller(void) { - n_callee(); - s_callee(); - sc_callee(); -} - - -// CHECK-LABEL: define {{[^@]+}}@s_caller -// CHECK-SAME: () #[[ATTR7:[0-9]+]] { -// CHECK: call void @n_callee() -// CHECK: call void @s_callee() #[[ATTR12]] -// CHECK: call void @sc_callee() #[[ATTR13]] -// -void s_caller(void) __arm_streaming { - n_callee(); - s_callee(); - sc_callee(); -} - - -// CHECK-LABEL: define {{[^@]+}}@sc_caller -// CHECK-SAME: () #[[ATTR11:[0-9]+]] { -// CHECK: call void @n_callee() -// CHECK: call void @s_callee() #[[ATTR12]] -// CHECK: call void @sc_callee() #[[ATTR13]] -// -void sc_caller(void) __arm_streaming_compatible { - n_callee(); - s_callee(); - sc_callee(); -} - - -// CHECK: attributes #[[ATTR0:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body" -// CHECK: attributes #[[ATTR1:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body" -// CHECK: attributes #[[ATTR2:[0-9]+]] = {{.*}} -// CHECK: attributes #[[ATTR3]] = {{.*}} -// CHECK: attributes #[[ATTR4:[0-9]+]] = {{.*}} "aarch64_pstate_sm_enabled" -// CHECK: attributes #[[ATTR5:[0-9]+]] = {{.*}} "aarch64_pstate_sm_enabled" -// CHECK: attributes #[[ATTR6:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_enabled" -// CHECK: attributes #[[ATTR7]] = {{.*}} "aarch64_pstate_sm_enabled" -// CHECK: attributes #[[ATTR8:[0-9]+]] = {{.*}} "aarch64_pstate_sm_compatible" -// CHECK: attributes #[[ATTR9:[0-9]+]] = {{.*}} "aarch64_pstate_sm_compatible" -// CHECK: attributes #[[ATTR10]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_compatible" -// CHECK: attributes #[[ATTR11]] = {{.*}} "aarch64_pstate_sm_compatible" -// CHECK: attributes #[[ATTR12]] = {{.*}} "aarch64_pstate_sm_enabled" -// CHECK: attributes #[[ATTR13]] = {{.*}} "aarch64_pstate_sm_compatible" diff --git a/clang/test/CodeGen/arm-bf16-convert-intrinsics.c b/clang/test/CodeGen/arm-bf16-convert-intrinsics.c index e2be98c086853ec6642e4958c77eef19464d8fe2..51aa5aa758f0c39ead8c29b1662f7c0c43efcee0 100644 --- a/clang/test/CodeGen/arm-bf16-convert-intrinsics.c +++ b/clang/test/CodeGen/arm-bf16-convert-intrinsics.c @@ -24,50 +24,50 @@ // CHECK-A64-LABEL: @test_vcvt_f32_bf16( // CHECK-A64-NEXT: entry: -// CHECK-A64-NEXT: [[__REINT_836_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A64-NEXT: [[__REINT1_836_I:%.*]] = alloca <4 x i32>, align 16 -// CHECK-A64-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_836_I]], align 8 -// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I]], align 8 +// CHECK-A64-NEXT: [[__REINT_808_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A64-NEXT: [[__REINT1_808_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-A64-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_808_I]], align 8 +// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_808_I]], align 8 // CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-A64-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A64-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> // CHECK-A64-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16) -// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_836_I]], align 16 -// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I]], align 16 +// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_808_I]], align 16 +// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_808_I]], align 16 // CHECK-A64-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-HARDFP-LABEL: @test_vcvt_f32_bf16( // CHECK-A32-HARDFP-NEXT: entry: -// CHECK-A32-HARDFP-NEXT: [[__REINT_836_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-HARDFP-NEXT: [[__REINT1_836_I:%.*]] = alloca <4 x i32>, align 8 -// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_836_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT_808_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT1_808_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[A:%.*]], ptr [[__REINT_808_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_808_I]], align 8 // CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> // CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16) -// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_836_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I]], align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_808_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_808_I]], align 8 // CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-SOFTFP-LABEL: @test_vcvt_f32_bf16( // CHECK-A32-SOFTFP-NEXT: entry: -// CHECK-A32-SOFTFP-NEXT: [[__P0_836_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT_836_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT1_836_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_808_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT_808_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT1_808_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-SOFTFP-NEXT: [[A:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[A_COERCE:%.*]], ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: [[A1:%.*]] = load <4 x bfloat>, ptr [[A]], align 8 // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[A1]], ptr [[COERCE]], align 8 // CHECK-A32-SOFTFP-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[COERCE]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP0]], ptr [[__P0_836_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_8361_I:%.*]] = load <4 x bfloat>, ptr [[__P0_836_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8361_I]], ptr [[__REINT_836_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP0]], ptr [[__P0_808_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_8081_I:%.*]] = load <4 x bfloat>, ptr [[__P0_808_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8081_I]], ptr [[__REINT_808_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr [[__REINT_808_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP1]] to <8 x i8> -// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32> +// CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32> // CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP3]], splat (i32 16) -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_836_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <4 x float>, ptr [[__REINT1_836_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I]], ptr [[__REINT1_808_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <4 x float>, ptr [[__REINT1_808_I]], align 8 // CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP4]] // float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) { @@ -76,39 +76,39 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) { // CHECK-A64-LABEL: @test_vcvtq_low_f32_bf16( // CHECK-A64-NEXT: entry: -// CHECK-A64-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A64-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-A64-NEXT: [[__REINT_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A64-NEXT: [[__REINT1_808_I_I:%.*]] = alloca <4 x i32>, align 16 // CHECK-A64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 -// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_808_I_I]], align 8 +// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_808_I_I]], align 8 // CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-A64-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A64-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> // CHECK-A64-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16) -// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 16 -// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 16 +// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_808_I_I]], align 16 +// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_808_I_I]], align 16 // CHECK-A64-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-HARDFP-LABEL: @test_vcvtq_low_f32_bf16( // CHECK-A32-HARDFP-NEXT: entry: -// CHECK-A32-HARDFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-HARDFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT1_808_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-HARDFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_808_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_808_I_I]], align 8 // CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> // CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16) -// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_808_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_808_I_I]], align 8 // CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-SOFTFP-LABEL: @test_vcvtq_low_f32_bf16( // CHECK-A32-SOFTFP-NEXT: entry: // CHECK-A32-SOFTFP-NEXT: [[RETVAL_I:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I2:%.*]] = alloca <8 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT1_808_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE2_I:%.*]] = alloca <4 x bfloat>, align 8 @@ -132,15 +132,15 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) { // CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <4 x bfloat>, ptr [[COERCE2_I]], align 8 // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP3]], ptr [[COERCE3_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <2 x i32>, ptr [[COERCE3_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_8361_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8361_I_I]], ptr [[__REINT_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_8081_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8081_I_I]], ptr [[__REINT_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_808_I_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = sext <4 x i16> [[TMP5]] to <4 x i32> +// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = zext <4 x i16> [[TMP5]] to <4 x i32> // CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP7]], splat (i32 16) -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[__REINT1_808_I_I]], align 8 // CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP8]] // float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) { @@ -149,39 +149,39 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) { // CHECK-A64-LABEL: @test_vcvtq_high_f32_bf16( // CHECK-A64-NEXT: entry: -// CHECK-A64-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A64-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 16 +// CHECK-A64-NEXT: [[__REINT_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A64-NEXT: [[__REINT1_808_I_I:%.*]] = alloca <4 x i32>, align 16 // CHECK-A64-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 -// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A64-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_808_I_I]], align 8 +// CHECK-A64-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_808_I_I]], align 8 // CHECK-A64-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-A64-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A64-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> // CHECK-A64-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16) -// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 16 -// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 16 +// CHECK-A64-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_808_I_I]], align 16 +// CHECK-A64-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_808_I_I]], align 16 // CHECK-A64-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-HARDFP-LABEL: @test_vcvtq_high_f32_bf16( // CHECK-A32-HARDFP-NEXT: entry: -// CHECK-A32-HARDFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-HARDFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-HARDFP-NEXT: [[__REINT1_808_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-HARDFP-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <8 x bfloat> [[A:%.*]], <8 x bfloat> [[A]], <4 x i32> -// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_836_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x bfloat> [[SHUFFLE_I]], ptr [[__REINT_808_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr [[__REINT_808_I_I]], align 8 // CHECK-A32-HARDFP-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8> -// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = sext <4 x i16> [[TMP0]] to <4 x i32> +// CHECK-A32-HARDFP-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[TMP0]] to <4 x i32> // CHECK-A32-HARDFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16) -// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 -// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_808_I_I]], align 8 +// CHECK-A32-HARDFP-NEXT: [[TMP3:%.*]] = load <4 x float>, ptr [[__REINT1_808_I_I]], align 8 // CHECK-A32-HARDFP-NEXT: ret <4 x float> [[TMP3]] // // CHECK-A32-SOFTFP-LABEL: @test_vcvtq_high_f32_bf16( // CHECK-A32-SOFTFP-NEXT: entry: // CHECK-A32-SOFTFP-NEXT: [[RETVAL_I:%.*]] = alloca <4 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I2:%.*]] = alloca <8 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT_836_I_I:%.*]] = alloca <4 x bfloat>, align 8 -// CHECK-A32-SOFTFP-NEXT: [[__REINT1_836_I_I:%.*]] = alloca <4 x i32>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT_808_I_I:%.*]] = alloca <4 x bfloat>, align 8 +// CHECK-A32-SOFTFP-NEXT: [[__REINT1_808_I_I:%.*]] = alloca <4 x i32>, align 8 // CHECK-A32-SOFTFP-NEXT: [[__P0_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE_I:%.*]] = alloca <8 x bfloat>, align 8 // CHECK-A32-SOFTFP-NEXT: [[COERCE2_I:%.*]] = alloca <4 x bfloat>, align 8 @@ -205,15 +205,15 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) { // CHECK-A32-SOFTFP-NEXT: [[TMP3:%.*]] = load <4 x bfloat>, ptr [[COERCE2_I]], align 8 // CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[TMP3]], ptr [[COERCE3_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[TMP4:%.*]] = load <2 x i32>, ptr [[COERCE3_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[__P0_8361_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8361_I_I]], ptr [[__REINT_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <2 x i32> [[TMP4]], ptr [[__P0_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[__P0_8081_I_I:%.*]] = load <4 x bfloat>, ptr [[__P0_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x bfloat> [[__P0_8081_I_I]], ptr [[__REINT_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP5:%.*]] = load <4 x i16>, ptr [[__REINT_808_I_I]], align 8 // CHECK-A32-SOFTFP-NEXT: [[TMP6:%.*]] = bitcast <4 x i16> [[TMP5]] to <8 x i8> -// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = sext <4 x i16> [[TMP5]] to <4 x i32> +// CHECK-A32-SOFTFP-NEXT: [[TMP7:%.*]] = zext <4 x i16> [[TMP5]] to <4 x i32> // CHECK-A32-SOFTFP-NEXT: [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP7]], splat (i32 16) -// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_836_I_I]], align 8 -// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[__REINT1_836_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: store <4 x i32> [[VSHLL_N_I_I]], ptr [[__REINT1_808_I_I]], align 8 +// CHECK-A32-SOFTFP-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[__REINT1_808_I_I]], align 8 // CHECK-A32-SOFTFP-NEXT: ret <4 x float> [[TMP8]] // float32x4_t test_vcvtq_high_f32_bf16(bfloat16x8_t a) { @@ -427,7 +427,7 @@ bfloat16_t test_vcvth_bf16_f32(float32_t a) { // CHECK-NEXT: [[__REINT1_I:%.*]] = alloca i32, align 4 // CHECK-NEXT: store bfloat [[A:%.*]], ptr [[__REINT_I]], align 2 // CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[__REINT_I]], align 2 -// CHECK-NEXT: [[CONV_I:%.*]] = sext i16 [[TMP0]] to i32 +// CHECK-NEXT: [[CONV_I:%.*]] = zext i16 [[TMP0]] to i32 // CHECK-NEXT: [[SHL_I:%.*]] = shl i32 [[CONV_I]], 16 // CHECK-NEXT: store i32 [[SHL_I]], ptr [[__REINT1_I]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[__REINT1_I]], align 4 diff --git a/clang/test/CodeGen/arm-mfp8.c b/clang/test/CodeGen/arm-mfp8.c index 8c817fd5be1c9bedc9a9e995e2c1d9c06b60c333..bf91066335a25c46e1f70068b2c089f00e541018 100644 --- a/clang/test/CodeGen/arm-mfp8.c +++ b/clang/test/CodeGen/arm-mfp8.c @@ -60,7 +60,7 @@ mfloat8x8_t test_ret_mfloat8x8_t(mfloat8x8_t v) { // CHECK-C-NEXT: [[TMP1:%.*]] = load <1 x i8>, ptr [[ARRAYIDX1]], align 1 // CHECK-C-NEXT: ret <1 x i8> [[TMP1]] // -// CHECK-CXX-LABEL: define dso_local <1 x i8> @_Z6func1nu11__MFloat8_t( +// CHECK-CXX-LABEL: define dso_local <1 x i8> @_Z6func1nu6__mfp8( // CHECK-CXX-SAME: <1 x i8> [[MFP8:%.*]]) #[[ATTR0]] { // CHECK-CXX-NEXT: [[ENTRY:.*:]] // CHECK-CXX-NEXT: [[MFP8_ADDR:%.*]] = alloca <1 x i8>, align 1 diff --git a/clang/test/CodeGen/arm-mve-intrinsics/compare.c b/clang/test/CodeGen/arm-mve-intrinsics/compare.c index 8f190990a65869af22692869874cc31562afacc3..8886cf5c100581cc65913328a5ded2e177cd2309 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/compare.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/compare.c @@ -2376,7 +2376,7 @@ mve_pred16_t test_vcmphiq_m_n_u32(uint32x4_t a, uint32_t b, mve_pred16_t p) // CHECK-LABEL: @test_vcmpleq_f16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = fcmp ole <8 x half> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ule <8 x half> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2392,7 +2392,7 @@ mve_pred16_t test_vcmpleq_f16(float16x8_t a, float16x8_t b) // CHECK-LABEL: @test_vcmpleq_f32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = fcmp ole <4 x float> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ule <4 x float> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2458,7 +2458,7 @@ mve_pred16_t test_vcmpleq_s32(int32x4_t a, int32x4_t b) // CHECK-NEXT: entry: // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> poison, half [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> poison, <8 x i32> zeroinitializer -// CHECK-NEXT: [[TMP0:%.*]] = fcmp ole <8 x half> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ule <8 x half> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2476,7 +2476,7 @@ mve_pred16_t test_vcmpleq_n_f16(float16x8_t a, float16_t b) // CHECK-NEXT: entry: // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer -// CHECK-NEXT: [[TMP0:%.*]] = fcmp ole <4 x float> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ule <4 x float> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2548,7 +2548,7 @@ mve_pred16_t test_vcmpleq_n_s32(int32x4_t a, int32_t b) // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = fcmp ole <8 x half> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ule <8 x half> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP3:%.*]] = and <8 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -2567,7 +2567,7 @@ mve_pred16_t test_vcmpleq_m_f16(float16x8_t a, float16x8_t b, mve_pred16_t p) // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = fcmp ole <4 x float> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ule <4 x float> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP3:%.*]] = and <4 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -2645,7 +2645,7 @@ mve_pred16_t test_vcmpleq_m_s32(int32x4_t a, int32x4_t b, mve_pred16_t p) // CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> poison, half [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> poison, <8 x i32> zeroinitializer -// CHECK-NEXT: [[TMP2:%.*]] = fcmp ole <8 x half> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ule <8 x half> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP3:%.*]] = and <8 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -2666,7 +2666,7 @@ mve_pred16_t test_vcmpleq_m_n_f16(float16x8_t a, float16_t b, mve_pred16_t p) // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer -// CHECK-NEXT: [[TMP2:%.*]] = fcmp ole <4 x float> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ule <4 x float> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP3:%.*]] = and <4 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -2746,7 +2746,7 @@ mve_pred16_t test_vcmpleq_m_n_s32(int32x4_t a, int32_t b, mve_pred16_t p) // CHECK-LABEL: @test_vcmpltq_f16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = fcmp olt <8 x half> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ult <8 x half> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2762,7 +2762,7 @@ mve_pred16_t test_vcmpltq_f16(float16x8_t a, float16x8_t b) // CHECK-LABEL: @test_vcmpltq_f32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = fcmp olt <4 x float> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ult <4 x float> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2828,7 +2828,7 @@ mve_pred16_t test_vcmpltq_s32(int32x4_t a, int32x4_t b) // CHECK-NEXT: entry: // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> poison, half [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> poison, <8 x i32> zeroinitializer -// CHECK-NEXT: [[TMP0:%.*]] = fcmp olt <8 x half> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ult <8 x half> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2846,7 +2846,7 @@ mve_pred16_t test_vcmpltq_n_f16(float16x8_t a, float16_t b) // CHECK-NEXT: entry: // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer -// CHECK-NEXT: [[TMP0:%.*]] = fcmp olt <4 x float> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP0:%.*]] = fcmp ult <4 x float> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP0]]) // CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16 // CHECK-NEXT: ret i16 [[TMP2]] @@ -2918,7 +2918,7 @@ mve_pred16_t test_vcmpltq_n_s32(int32x4_t a, int32_t b) // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = fcmp olt <8 x half> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ult <8 x half> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP3:%.*]] = and <8 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -2937,7 +2937,7 @@ mve_pred16_t test_vcmpltq_m_f16(float16x8_t a, float16x8_t b, mve_pred16_t p) // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = fcmp olt <4 x float> [[A:%.*]], [[B:%.*]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ult <4 x float> [[A:%.*]], [[B:%.*]] // CHECK-NEXT: [[TMP3:%.*]] = and <4 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -3015,7 +3015,7 @@ mve_pred16_t test_vcmpltq_m_s32(int32x4_t a, int32x4_t b, mve_pred16_t p) // CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> poison, half [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> poison, <8 x i32> zeroinitializer -// CHECK-NEXT: [[TMP2:%.*]] = fcmp olt <8 x half> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ult <8 x half> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP3:%.*]] = and <8 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v8i1(<8 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 @@ -3036,7 +3036,7 @@ mve_pred16_t test_vcmpltq_m_n_f16(float16x8_t a, float16_t b, mve_pred16_t p) // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) // CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[B:%.*]], i64 0 // CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer -// CHECK-NEXT: [[TMP2:%.*]] = fcmp olt <4 x float> [[A:%.*]], [[DOTSPLAT]] +// CHECK-NEXT: [[TMP2:%.*]] = fcmp ult <4 x float> [[A:%.*]], [[DOTSPLAT]] // CHECK-NEXT: [[TMP3:%.*]] = and <4 x i1> [[TMP1]], [[TMP2]] // CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.arm.mve.pred.v2i.v4i1(<4 x i1> [[TMP3]]) // CHECK-NEXT: [[TMP5:%.*]] = trunc i32 [[TMP4]] to i16 diff --git a/clang/test/CodeGen/arm-mve-intrinsics/ternary.c b/clang/test/CodeGen/arm-mve-intrinsics/ternary.c index 36b2ce063cb188a9145ed8f867344d8fa92b9a6e..768d397cb5611fc8ad50e66ce5c261eaeb62d951 100644 --- a/clang/test/CodeGen/arm-mve-intrinsics/ternary.c +++ b/clang/test/CodeGen/arm-mve-intrinsics/ternary.c @@ -542,12 +542,13 @@ float32x4_t test_vfmaq_m_n_f32(float32x4_t a, float32x4_t b, float32_t c, mve_pr // CHECK-LABEL: @test_vfmasq_m_n_f16( // CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> poison, half [[C:%.*]], i64 0 -// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> poison, <8 x i32> zeroinitializer // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <8 x half> @llvm.arm.mve.fma.predicated.v8f16.v8i1(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]], <8 x half> [[DOTSPLAT]], <8 x i1> [[TMP1]]) -// CHECK-NEXT: ret <8 x half> [[TMP2]] +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <8 x half> poison, half [[C:%.*]], i64 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <8 x half> [[DOTSPLATINSERT]], <8 x half> poison, <8 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = call <8 x half> @llvm.fma.v8f16(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]], <8 x half> [[DOTSPLAT]]) +// CHECK-NEXT: [[TMP3:%.*]] = select <8 x i1> [[TMP1]], <8 x half> [[TMP2]], <8 x half> [[A]] +// CHECK-NEXT: ret <8 x half> [[TMP3]] // float16x8_t test_vfmasq_m_n_f16(float16x8_t a, float16x8_t b, float16_t c, mve_pred16_t p) { #ifdef POLYMORPHIC @@ -559,12 +560,13 @@ float16x8_t test_vfmasq_m_n_f16(float16x8_t a, float16x8_t b, float16_t c, mve_p // CHECK-LABEL: @test_vfmasq_m_n_f32( // CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[C:%.*]], i64 0 -// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer // CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 // CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) -// CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.arm.mve.fma.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]], <4 x float> [[DOTSPLAT]], <4 x i1> [[TMP1]]) -// CHECK-NEXT: ret <4 x float> [[TMP2]] +// CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <4 x float> poison, float [[C:%.*]], i64 0 +// CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <4 x float> [[DOTSPLATINSERT]], <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = call <4 x float> @llvm.fma.v4f32(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]], <4 x float> [[DOTSPLAT]]) +// CHECK-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP1]], <4 x float> [[TMP2]], <4 x float> [[A]] +// CHECK-NEXT: ret <4 x float> [[TMP3]] // float32x4_t test_vfmasq_m_n_f32(float32x4_t a, float32x4_t b, float32_t c, mve_pred16_t p) { #ifdef POLYMORPHIC diff --git a/clang/test/CodeGen/arm-vfp16-arguments.c b/clang/test/CodeGen/arm-vfp16-arguments.c index da034626024f82c633adf035ed7c45a3d0aa3e58..3c6691df4747abb8164d91dece21ba458fe7f638 100644 --- a/clang/test/CodeGen/arm-vfp16-arguments.c +++ b/clang/test/CodeGen/arm-vfp16-arguments.c @@ -71,6 +71,6 @@ void test_hfa(hfa_t a) {} hfa_t ghfa; hfa_t test_ret_hfa(void) { return ghfa; } -// CHECK-SOFT: define{{.*}} void @test_ret_hfa(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.hfa_t) align 8 %agg.result) +// CHECK-SOFT: define{{.*}} void @test_ret_hfa(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.hfa_t) align 8 initializes((0, 16)) %agg.result) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @test_ret_hfa() // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.hfa_t @test_ret_hfa() diff --git a/clang/test/CodeGen/arm-vfp16-arguments2.cpp b/clang/test/CodeGen/arm-vfp16-arguments2.cpp index b7c6852c47b7f077eb34d5b5e0d89675cf6088ed..b810cfd0a6648f90a88ab81017188319d59946ec 100644 --- a/clang/test/CodeGen/arm-vfp16-arguments2.cpp +++ b/clang/test/CodeGen/arm-vfp16-arguments2.cpp @@ -37,27 +37,27 @@ struct S5 : B1 { B1 M[1]; }; -// CHECK-SOFT: define{{.*}} void @_Z2f12S1(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S1) align 8 %agg.result, [2 x i64] %s1.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f12S1(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S1) align 8 initializes((0, 16)) %agg.result, [2 x i64] %s1.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f12S1([2 x <2 x i32>] returned %s1.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S1 @_Z2f12S1(%struct.S1 returned %s1.coerce) struct S1 f1(struct S1 s1) { return s1; } -// CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S2) align 8 %agg.result, [4 x i32] %s2.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f22S2(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S2) align 8 initializes((0, 16)) %agg.result, [4 x i32] %s2.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f22S2([2 x <2 x i32>] returned %s2.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S2 @_Z2f22S2(%struct.S2 %s2.coerce) struct S2 f2(struct S2 s2) { return s2; } -// CHECK-SOFT: define{{.*}} void @_Z2f32S3(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S3) align 8 %agg.result, [2 x i64] %s3.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f32S3(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S3) align 8 initializes((0, 16)) %agg.result, [2 x i64] %s3.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f32S3([2 x <2 x i32>] returned %s3.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S3 @_Z2f32S3(%struct.S3 %s3.coerce) struct S3 f3(struct S3 s3) { return s3; } -// CHECK-SOFT: define{{.*}} void @_Z2f42S4(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S4) align 8 %agg.result, [2 x i64] %s4.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f42S4(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S4) align 8 initializes((0, 16)) %agg.result, [2 x i64] %s4.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @_Z2f42S4([2 x <2 x i32>] returned %s4.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S4 @_Z2f42S4(%struct.S4 %s4.coerce) struct S4 f4(struct S4 s4) { return s4; } -// CHECK-SOFT: define{{.*}} void @_Z2f52S5(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S5) align 8 %agg.result, [2 x i64] %s5.coerce) +// CHECK-SOFT: define{{.*}} void @_Z2f52S5(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.S5) align 8 initializes((0, 16)) %agg.result, [2 x i64] %s5.coerce) // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc %struct.S5 @_Z2f52S5(%struct.S5 %s5.coerce) // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.S5 @_Z2f52S5(%struct.S5 %s5.coerce) struct S5 f5(struct S5 s5) { return s5; } diff --git a/clang/test/CodeGen/attr-cpuspecific-cpus.c b/clang/test/CodeGen/attr-cpuspecific-cpus.c index dd154fd227b25bf94d5819dc21c40152d41552fc..1dd095ec9e191ffe9f7ae0ae11c39edb62736d3c 100644 --- a/clang/test/CodeGen/attr-cpuspecific-cpus.c +++ b/clang/test/CodeGen/attr-cpuspecific-cpus.c @@ -43,6 +43,7 @@ ATTR(cpu_specific(icelake_client)) void CPU(void){} ATTR(cpu_specific(tigerlake)) void CPU(void){} ATTR(cpu_specific(alderlake)) void CPU(void){} ATTR(cpu_specific(sapphirerapids)) void CPU(void){} +ATTR(cpu_specific(diamondrapids)) void CPU(void){} // ALIAS CPUs ATTR(cpu_specific(pentium_iii_no_xmm_regs)) void CPU0(void){} diff --git a/clang/test/CodeGen/attr-ifunc.c b/clang/test/CodeGen/attr-ifunc.c index 24d66433ae090f5a980e2dcf839f58283d871e79..c9e70b17a83023fba21407ff2aa1c1ab8a37559d 100644 --- a/clang/test/CodeGen/attr-ifunc.c +++ b/clang/test/CodeGen/attr-ifunc.c @@ -2,8 +2,10 @@ // RUN: %clang_cc1 -triple x86_64-linux -verify -emit-llvm-only -DCHECK_ALIASES %s // RUN: %clang_cc1 -triple x86_64-linux -verify -emit-llvm-only %s // RUN: %clang_cc1 -triple x86_64-apple-macosx -verify -emit-llvm-only %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -verify -emit-llvm-only %s +// RUN: %clang_cc1 -triple aarch64-pc-windows-msvcu -verify -emit-llvm-only %s -#if defined(_WIN32) +#if defined(_WIN32) && !defined(__aarch64__) void foo(void) {} void bar(void) __attribute__((ifunc("foo"))); // expected-warning@-1 {{unknown attribute 'ifunc' ignored}} diff --git a/clang/test/CodeGen/attr-target-clones-aarch64.c b/clang/test/CodeGen/attr-target-clones-aarch64.c index 1dc4044788b68333e2af11eaf4473d0dde5dd7c4..961279424754d508fd3cca47779b8991d7505861 100644 --- a/clang/test/CodeGen/attr-target-clones-aarch64.c +++ b/clang/test/CodeGen/attr-target-clones-aarch64.c @@ -252,56 +252,56 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_def.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_dup1.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_dup2.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_dup3.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline2._Mfp16 -// CHECK-SAME: () #[[ATTR9:[0-9]+]] { +// CHECK-SAME: () #[[ATTR10:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline2._MfcmaMsve2-bitperm -// CHECK-SAME: () #[[ATTR10:[0-9]+]] { +// CHECK-SAME: () #[[ATTR11:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline2.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // @@ -330,28 +330,28 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline1._MrngMsimd -// CHECK-SAME: () #[[ATTR11:[0-9]+]] { +// CHECK-SAME: () #[[ATTR12:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline1._MpredresMrcpc -// CHECK-SAME: () #[[ATTR12:[0-9]+]] { +// CHECK-SAME: () #[[ATTR13:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline1._Msve2-aesMwfxt -// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-SAME: () #[[ATTR14:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline1.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // @@ -395,14 +395,14 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline3._MsbMsve -// CHECK-SAME: () #[[ATTR14:[0-9]+]] { +// CHECK-SAME: () #[[ATTR15:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@ftc_inline3.default -// CHECK-SAME: () #[[ATTR8]] { +// CHECK-SAME: () #[[ATTR9]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // @@ -670,7 +670,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@foo -// CHECK-MTE-BTI-SAME: () #[[ATTR5]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR6:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: [[CALL:%.*]] = call i32 @ftc() // CHECK-MTE-BTI-NEXT: [[CALL1:%.*]] = call i32 @ftc_def() @@ -686,14 +686,14 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_direct -// CHECK-MTE-BTI-SAME: () #[[ATTR5]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR6]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 4 // // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@main -// CHECK-MTE-BTI-SAME: () #[[ATTR5]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR6]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-MTE-BTI-NEXT: store i32 0, ptr [[RETVAL]], align 4 @@ -744,14 +744,14 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_inline2._Mfp16 -// CHECK-MTE-BTI-SAME: () #[[ATTR6:[0-9]+]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR7:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 2 // // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_inline2._MfcmaMsve2-bitperm -// CHECK-MTE-BTI-SAME: () #[[ATTR7:[0-9]+]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR8:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 2 // @@ -787,21 +787,21 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_inline1._MrngMsimd -// CHECK-MTE-BTI-SAME: () #[[ATTR8:[0-9]+]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR9:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 1 // // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_inline1._MpredresMrcpc -// CHECK-MTE-BTI-SAME: () #[[ATTR9:[0-9]+]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR10:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 1 // // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_inline1._Msve2-aesMwfxt -// CHECK-MTE-BTI-SAME: () #[[ATTR10:[0-9]+]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR11:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 1 // @@ -852,7 +852,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // CHECK-MTE-BTI: Function Attrs: noinline nounwind optnone // CHECK-MTE-BTI-LABEL: define {{[^@]+}}@ftc_inline3._MsbMsve -// CHECK-MTE-BTI-SAME: () #[[ATTR11:[0-9]+]] { +// CHECK-MTE-BTI-SAME: () #[[ATTR12:[0-9]+]] { // CHECK-MTE-BTI-NEXT: entry: // CHECK-MTE-BTI-NEXT: ret i32 3 // diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c index 2c4b95ca04370a02fbc8be6f12833b77418fa7c1..6911b55203b7e7e9d4f9dfa7393edc3595cf49ea 100644 --- a/clang/test/CodeGen/attr-target-mv.c +++ b/clang/test/CodeGen/attr-target-mv.c @@ -29,6 +29,7 @@ int __attribute__((target("arch=lunarlake"))) foo(void) {return 23;} int __attribute__((target("arch=gracemont"))) foo(void) {return 24;} int __attribute__((target("arch=pantherlake"))) foo(void) {return 25;} int __attribute__((target("arch=clearwaterforest"))) foo(void) {return 26;} +int __attribute__((target("arch=diamondrapids"))) foo(void) {return 27;} int __attribute__((target("default"))) foo(void) { return 2; } int bar(void) { diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index f0d98412ff4f2b913068b0b194f517fdee991da2..4194ce26870504c69998c0e814eea497b4f8f364 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -248,14 +248,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_two._Msimd -// CHECK-SAME: () #[[ATTR12]] { +// CHECK-SAME: () #[[ATTR13:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp16Msimd -// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-SAME: () #[[ATTR14:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // @@ -269,7 +269,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@foo -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one() @@ -288,7 +288,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs -// CHECK-SAME: () #[[ATTR14:[0-9]+]] { +// CHECK-SAME: () #[[ATTR16:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret void // @@ -302,7 +302,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@goo -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e() @@ -321,7 +321,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@recur -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: call void @reca() // CHECK-NEXT: ret void @@ -329,7 +329,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@hoo -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[FP1:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[FP2:%.*]] = alloca ptr, align 8 @@ -346,14 +346,14 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_forward_default_decl._Mmops -// CHECK-SAME: () #[[ATTR16:[0-9]+]] { +// CHECK-SAME: () #[[ATTR19:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_extern_forward_default_decl._Mdotprod -// CHECK-SAME: () #[[ATTR17:[0-9]+]] { +// CHECK-SAME: () #[[ATTR20:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // @@ -367,7 +367,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_default_def._Msve -// CHECK-SAME: () #[[ATTR18:[0-9]+]] { +// CHECK-SAME: () #[[ATTR21:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // @@ -381,7 +381,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def._Mfp16 -// CHECK-SAME: () #[[ATTR13]] { +// CHECK-SAME: () #[[ATTR22:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // @@ -395,49 +395,49 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def._Mlse -// CHECK-SAME: () #[[ATTR19:[0-9]+]] { +// CHECK-SAME: () #[[ATTR23:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@unused_without_default._Mrdm -// CHECK-SAME: () #[[ATTR20:[0-9]+]] { +// CHECK-SAME: () #[[ATTR24:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.default -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mjscvt -// CHECK-SAME: () #[[ATTR22:[0-9]+]] { +// CHECK-SAME: () #[[ATTR26:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mrdm -// CHECK-SAME: () #[[ATTR20]] { +// CHECK-SAME: () #[[ATTR24]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@caller -// CHECK-SAME: () #[[ATTR9]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @used_def_without_default_decl() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @used_decl_without_default_decl() @@ -602,7 +602,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_d._Msb -// CHECK-SAME: () #[[ATTR24:[0-9]+]] { +// CHECK-SAME: () #[[ATTR28:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // @@ -644,112 +644,112 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MaesMf64mmMsha2 -// CHECK-SAME: () #[[ATTR25:[0-9]+]] { +// CHECK-SAME: () #[[ATTR29:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16MrdmMsme -// CHECK-SAME: () #[[ATTR26:[0-9]+]] { +// CHECK-SAME: () #[[ATTR30:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf32mmMi8mmMsha3 -// CHECK-SAME: () #[[ATTR27:[0-9]+]] { +// CHECK-SAME: () #[[ATTR31:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 12 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mbf16Mdit -// CHECK-SAME: () #[[ATTR28:[0-9]+]] { +// CHECK-SAME: () #[[ATTR32:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 8 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MdpbMrcpc2 -// CHECK-SAME: () #[[ATTR29:[0-9]+]] { +// CHECK-SAME: () #[[ATTR33:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 6 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mdpb2Mjscvt -// CHECK-SAME: () #[[ATTR30:[0-9]+]] { +// CHECK-SAME: () #[[ATTR34:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 7 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfrinttsMrcpc -// CHECK-SAME: () #[[ATTR31:[0-9]+]] { +// CHECK-SAME: () #[[ATTR35:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mbf16Msve -// CHECK-SAME: () #[[ATTR32:[0-9]+]] { +// CHECK-SAME: () #[[ATTR36:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2-aesMsve2-sha3 -// CHECK-SAME: () #[[ATTR33:[0-9]+]] { +// CHECK-SAME: () #[[ATTR37:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 5 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2Msve2-aesMsve2-bitperm -// CHECK-SAME: () #[[ATTR34:[0-9]+]] { +// CHECK-SAME: () #[[ATTR38:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 9 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MmemtagMsve2-sm4 -// CHECK-SAME: () #[[ATTR35:[0-9]+]] { +// CHECK-SAME: () #[[ATTR39:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 10 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MmemtagMmopsMrcpc3 -// CHECK-SAME: () #[[ATTR36:[0-9]+]] { +// CHECK-SAME: () #[[ATTR40:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 11 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MaesMdotprod -// CHECK-SAME: () #[[ATTR37:[0-9]+]] { +// CHECK-SAME: () #[[ATTR41:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 13 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mfp16fmlMsimd -// CHECK-SAME: () #[[ATTR38:[0-9]+]] { +// CHECK-SAME: () #[[ATTR42:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 14 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfpMsm4 -// CHECK-SAME: () #[[ATTR39:[0-9]+]] { +// CHECK-SAME: () #[[ATTR43:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 15 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MlseMrdm -// CHECK-SAME: () #[[ATTR40:[0-9]+]] { +// CHECK-SAME: () #[[ATTR44:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 16 // @@ -973,21 +973,21 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1:[0-9]+]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 0 // // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_one -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 0 // // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_two -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 0 // @@ -1013,21 +1013,21 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_d -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 1 // // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_c -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret void // // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_default -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 111 // @@ -1080,7 +1080,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@main -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-NOFMV-NEXT: store i32 0, ptr [[RETVAL]], align 4 @@ -1091,7 +1091,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_default_def -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR1]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: ret i32 1 // diff --git a/clang/test/CodeGen/blocks.c b/clang/test/CodeGen/blocks.c index d508de9c9f80143f2d5462e2d088f3aaabe7cf0a..d104078a9816cce411e9be047e3cca376892827a 100644 --- a/clang/test/CodeGen/blocks.c +++ b/clang/test/CodeGen/blocks.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=CHECK --check-prefix=SIG_STR %s // RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks -fdisable-block-signature-string | FileCheck --check-prefix=CHECK --check-prefix=NO_SIG_STR %s +// RUN: %clang_cc1 -triple s390x-unknown-unknown %s -emit-llvm -Wno-strict-prototypes -o - -fblocks | FileCheck --check-prefix=SYSTEMZ %s // SIG_STR: @[[STR:.*]] = private unnamed_addr constant [6 x i8] c"v4@?0\00", align 1 // SIG_STR: @{{.*}} = internal constant { ptr, i32, i32, ptr, ptr } { ptr @_NSConcreteGlobalBlock, i32 1342177280, i32 0, ptr @f_block_invoke, ptr @{{.*}} }, align 4 @@ -50,6 +51,8 @@ void (^test1)(void) = ^(void) { // CHECK-NEXT: call void @_Block_object_assign(ptr %[[V5]], ptr %[[BLOCKCOPY_SRC]], i32 8) // CHECK-NEXT: ret void +// SYSTEMZ: declare void @_Block_object_assign(ptr noundef, ptr noundef, i32 noundef signext) + // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_4_20r(ptr noundef %0) unnamed_addr // CHECK: %[[_ADDR:.*]] = alloca ptr, align 4 // CHECK-NEXT: store ptr %0, ptr %[[_ADDR]], align 4 @@ -59,6 +62,8 @@ void (^test1)(void) = ^(void) { // CHECK-NEXT: call void @_Block_object_dispose(ptr %[[V3]], i32 8) // CHECK-NEXT: ret void +// SYSTEMZ: declare void @_Block_object_dispose(ptr noundef, i32 noundef signext) + typedef double ftype(double); // It's not clear that we *should* support this syntax, but until that decision // is made, we should support it properly and not crash. diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c index aa77620b445356879a75c039435a923659331c32..68b9e75283c547f4de033bc9d3313274d8fc7edd 100644 --- a/clang/test/CodeGen/constrained-math-builtins.c +++ b/clang/test/CodeGen/constrained-math-builtins.c @@ -57,6 +57,13 @@ __builtin_atan(f); __builtin_atanf(f); __builtin_atanl(f); __builti // CHECK: call x86_fp80 @llvm.experimental.constrained.atan.f80(x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") // CHECK: call fp128 @llvm.experimental.constrained.atan.f128(fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +__builtin_atan2(f,f); __builtin_atan2f(f,f); __builtin_atan2l(f,f); __builtin_atan2f128(f,f); + +// CHECK: call double @llvm.experimental.constrained.atan2.f64(double %{{.*}}, double %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call float @llvm.experimental.constrained.atan2.f32(float %{{.*}}, float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call x86_fp80 @llvm.experimental.constrained.atan2.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call fp128 @llvm.experimental.constrained.atan2.f128(fp128 %{{.*}}, fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") + __builtin_ceil(f); __builtin_ceilf(f); __builtin_ceill(f); __builtin_ceilf128(f); // CHECK: call double @llvm.experimental.constrained.ceil.f64(double %{{.*}}, metadata !"fpexcept.strict") diff --git a/clang/test/CodeGen/embed-bitcode-marker-with-nonzero-as.c b/clang/test/CodeGen/embed-bitcode-marker-with-nonzero-as.c new file mode 100644 index 0000000000000000000000000000000000000000..df7118859c76402998fc6667bb06aa1c9b7e0be6 --- /dev/null +++ b/clang/test/CodeGen/embed-bitcode-marker-with-nonzero-as.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple spirv64-amd-amdhsa -emit-llvm -fcuda-is-device -fembed-bitcode=marker -x hip %s -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK + +// CHECK: @llvm.embedded.module = private addrspace(1) constant [0 x i8] zeroinitializer, section ".llvmbc", align 1 +// CHECK-NEXT: @llvm.cmdline = private addrspace(1) constant [{{[0-9]+}} x i8] c"{{.*}}", section ".llvmcmd", align 1 +// CHECK-NEXT: @llvm.compiler.used = appending addrspace(1) global [5 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @foo.managed to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @foo to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @__hip_cuid_ to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.cmdline to ptr addrspace(4))], section "llvm.metadata" + +__attribute__((managed)) int foo = 42; diff --git a/clang/test/CodeGen/ifunc-win.c b/clang/test/CodeGen/ifunc-win.c new file mode 100644 index 0000000000000000000000000000000000000000..deda51757e43be1c6623158b9646d080b3cd9386 --- /dev/null +++ b/clang/test/CodeGen/ifunc-win.c @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -triple aarch64-pc-windows-msvc -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-pc-windows-msvc -O2 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-pc-windows-msvc -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN +// RUN: %clang_cc1 -triple aarch64-pc-windows-msvc -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN + +// REQUIRES: aarch64-registered-target + +int foo(int) __attribute__ ((ifunc("foo_ifunc"))); + +static int f1(int i) { + return i + 1; +} + +static int f2(int i) { + return i + 2; +} + +typedef int (*foo_t)(int); + +volatile int global; + +static foo_t foo_ifunc(void) { + return global ? f1 : f2; +} + +int bar(void) { + return foo(1); +} + +extern void goo(void); + +void bar2(void) { + goo(); +} + +extern void goo(void) __attribute__ ((ifunc("goo_ifunc"))); + +void* goo_ifunc(void) { + return 0; +} + +/// The ifunc is emitted after its resolver. +void *hoo_ifunc(void) { return 0; } +extern void hoo(int) __attribute__ ((ifunc("hoo_ifunc"))); + +/// ifunc on Windows is lowered to global pointers and an indirect call. +// CHECK: @global = dso_local global i32 0, align 4 +// CHECK: {{.*}} = internal{{.*}}global{{.*}}poison, align 8 +/// Register the constructor for initialisation. +// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 10, ptr @{{.*}}, ptr null }] + +// CHECK-LABEL: @bar() +// CHECK %0 = load ptr, ptr @0, align 8 +// CHECK %call = call i32 %0(i32 noundef 1) + +// CHECK-LABEL: @bar2() +// CHECK %0 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @0, i32 0, i32 1), align 8 +// CHECK call void %0() + +// CHECK: define internal void @{{.*}}() + +// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @goo_ifunc() {{(local_unnamed_addr )?}} + +// SAN: define {{(dso_local )?}}noalias {{(noundef )?}}ptr @hoo_ifunc() {{(local_unnamed_addr )?}} + +// SAN: define internal {{(fastcc )?}}{{(noundef )?}}nonnull ptr @foo_ifunc() {{(unnamed_addr )?}} + diff --git a/clang/test/CodeGen/ifunc.c b/clang/test/CodeGen/ifunc.c index 2849246f93dc3ba3c6384c5c9e8a92e9ad2b9b4a..7d21f742e86765dcc30a609940ee16a8fd995535 100644 --- a/clang/test/CodeGen/ifunc.c +++ b/clang/test/CodeGen/ifunc.c @@ -12,6 +12,11 @@ // RUN: %clang_cc1 -triple arm64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN // RUN: %clang_cc1 -triple x86_64-apple-macosx -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN // RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=AVR +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsanitize=thread -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsanitize=address -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=SAN + /// The ifunc is emitted before its resolver. int foo(int) __attribute__ ((ifunc("foo_ifunc"))); diff --git a/clang/test/CodeGen/isfpclass.c b/clang/test/CodeGen/isfpclass.c index a0e04eaad5929dd16578e1817762ff81f27ef485..1bf60b8fbca176f131684897fa199fc9e9dfbe2f 100644 --- a/clang/test/CodeGen/isfpclass.c +++ b/clang/test/CodeGen/isfpclass.c @@ -160,7 +160,7 @@ int4 check_isfpclass_nan_strict_v4f32(float4 x) { } // CHECK-LABEL: define dso_local void @check_isfpclass_nan_v4f64 -// CHECK-SAME: (ptr dead_on_unwind noalias nocapture writable writeonly sret(<4 x i64>) align 16 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { +// CHECK-SAME: (ptr dead_on_unwind noalias nocapture writable writeonly sret(<4 x i64>) align 16 initializes((0, 32)) [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[TMP0:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[X:%.*]] = load <4 x double>, ptr [[TMP0]], align 16, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: [[TMP1:%.*]] = fcmp uno <4 x double> [[X]], zeroinitializer diff --git a/clang/test/CodeGen/libcalls.c b/clang/test/CodeGen/libcalls.c index b1637121127c5b967b326eb63d22b0b683f8513a..1e4b06e34aaf92dc93880c214065f1ad2c399745 100644 --- a/clang/test/CodeGen/libcalls.c +++ b/clang/test/CodeGen/libcalls.c @@ -95,9 +95,9 @@ void test_builtins(double d, float f, long double ld) { double atan2_ = atan2(d, 2); long double atan2l_ = atan2l(ld, ld); float atan2f_ = atan2f(f, f); -// CHECK-NO: declare double @atan2(double noundef, double noundef) [[NUW_RN:#[0-9]+]] -// CHECK-NO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NUW_RN]] -// CHECK-NO: declare float @atan2f(float noundef, float noundef) [[NUW_RN]] +// CHECK-NO: declare double @llvm.atan2.f64(double, double) [[NUW_RNI]] +// CHECK-NO: declare x86_fp80 @llvm.atan2.f80(x86_fp80, x86_fp80) [[NUW_RNI]] +// CHECK-NO: declare float @llvm.atan2.f32(float, float) [[NUW_RNI]] // CHECK-YES: declare double @atan2(double noundef, double noundef) [[NUW]] // CHECK-YES: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NUW]] // CHECK-YES: declare float @atan2f(float noundef, float noundef) [[NUW]] @@ -124,5 +124,4 @@ void test_builtins(double d, float f, long double ld) { } // CHECK-YES: attributes [[NUW]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+x87" } -// CHECK-NO-DAG: attributes [[NUW_RN]] = { nounwind willreturn memory(none){{.*}} } // CHECK-NO-DAG: attributes [[NUW_RNI]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } diff --git a/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c b/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c index 8e5f015647e4141f16c33a5ab7e3377a65056820..440db83fef5daafa40a0596bde0698fb502bd05e 100644 --- a/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c +++ b/clang/test/CodeGen/math-libcalls-tbaa-indirect-args.c @@ -53,7 +53,7 @@ long double powl(long double a, long double b); // CHECK-SPIR: [[CALL:%.*]] = tail call spir_func double @powl(double noundef [[A]], double noundef [[B]]) #[[ATTR3:[0-9]+]], !tbaa [[TBAA2:![0-9]+]] // // CHECK-MINGW32-LABEL: define dso_local void @test_powl( -// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret(x86_fp80) align 16 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[TMP0:%.*]], ptr nocapture noundef readonly [[TMP1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret(x86_fp80) align 16 initializes((0, 10)) [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[TMP0:%.*]], ptr nocapture noundef readonly [[TMP1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-MINGW32: [[A:%.*]] = load x86_fp80, ptr [[TMP0]], align 16, !tbaa [[TBAA3:![0-9]+]] // CHECK-MINGW32: [[B:%.*]] = load x86_fp80, ptr [[TMP1]], align 16, !tbaa [[TBAA3]] // CHECK-MINGW32: store x86_fp80 [[A]], ptr [[BYVAL_TEMP:%.*]], align 16, !tbaa [[TBAA3]] @@ -83,7 +83,7 @@ long double test_powl(long double a, long double b) { // CHECK-WIN64: [[CALL:%.*]] = tail call x86_fp80 @cargl(ptr noundef nonnull byval({ x86_fp80, x86_fp80 }) align 16 [[BYVAL_TEMP]]) #[[ATTR5]] // // CHECK-I686-LABEL: define dso_local void @test_cargl( -// CHECK-I686-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ x86_fp80, x86_fp80 }) align 4 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly byval({ x86_fp80, x86_fp80 }) align 4 [[CLD:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-I686-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ x86_fp80, x86_fp80 }) align 4 initializes((0, 10), (12, 22)) [[AGG_RESULT:%.*]], ptr nocapture noundef readonly byval({ x86_fp80, x86_fp80 }) align 4 [[CLD:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { // CHECK-I686: [[CLD_REAL:%.*]] = load x86_fp80, ptr [[CLD]], align 4 // CHECK-I686: [[CLD_IMAG:%.*]] = load x86_fp80, ptr [[CLD_IMAGP:%.*]], align 4 // CHECK-I686: store x86_fp80 [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 4 @@ -93,7 +93,7 @@ long double test_powl(long double a, long double b) { // CHECK-I686: store x86_fp80 [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 4 // // CHECK-PPC-LABEL: define dso_local void @test_cargl( -// CHECK-PPC-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ ppc_fp128, ppc_fp128 }) align 16 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly byval({ ppc_fp128, ppc_fp128 }) align 16 [[CLD:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-PPC-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ ppc_fp128, ppc_fp128 }) align 16 initializes((0, 32)) [[AGG_RESULT:%.*]], ptr nocapture noundef readonly byval({ ppc_fp128, ppc_fp128 }) align 16 [[CLD:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { // CHECK-PPC: [[CLD_REAL:%.*]] = load ppc_fp128, ptr [[CLD]], align 16 // CHECK-PPC: [[CLD_IMAG:%.*]] = load ppc_fp128, ptr [[CLD_IMAGP:%.*]], align 16 // CHECK-PPC: store ppc_fp128 [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 16 @@ -103,7 +103,7 @@ long double test_powl(long double a, long double b) { // CHECK-PPC: store ppc_fp128 [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 16 // // CHECK-ARM-LABEL: define dso_local void @test_cargl( -// CHECK-ARM-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ double, double }) align 8 [[AGG_RESULT:%.*]], [2 x i64] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-ARM-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ double, double }) align 8 initializes((0, 16)) [[AGG_RESULT:%.*]], [2 x i64] noundef [[CLD_COERCE:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { // CHECK-ARM: [[CALL:%.*]] = tail call double @cargl([2 x i64] noundef [[CLD_COERCE]]) #[[ATTR2]], !tbaa [[TBAA3]] // CHECK-ARM: store double [[MUL_RL:%.*]], ptr [[AGG_RESULT]], align 8 // CHECK-ARM: store double [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 8 @@ -121,7 +121,7 @@ long double test_powl(long double a, long double b) { // CHECK-AARCH: [[CALL:%.*]] = tail call fp128 @cargl([2 x fp128] noundef alignstack(16) [[CLD_COERCE]]) #[[ATTR2]], !tbaa [[TBAA2]] // // CHECK-SPIR-LABEL: define dso_local spir_func void @test_cargl( -// CHECK-SPIR-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ double, double }) align 8 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly byval({ double, double }) align 8 [[CLD:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-SPIR-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ double, double }) align 8 initializes((0, 16)) [[AGG_RESULT:%.*]], ptr nocapture noundef readonly byval({ double, double }) align 8 [[CLD:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { // CHECK-SPIR: [[CLD_REAL:%.*]] = load double, ptr [[CLD]], align 8 // CHECK-SPIR: [[CLD_IMAG:%.*]] = load double, ptr [[CLD_IMAGP:%.*]], align 8 // CHECK-SPIR: store double [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 8 @@ -131,7 +131,7 @@ long double test_powl(long double a, long double b) { // CHECK-SPIR: store double [[MUL_IR:%.*]], ptr [[AGG_RESULT_IMAGP:%.*]], align 8 // // CHECK-MINGW32-LABEL: define dso_local void @test_cargl( -// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ x86_fp80, x86_fp80 }) align 16 [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[CLD:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-MINGW32-SAME: ptr dead_on_unwind noalias nocapture writable writeonly sret({ x86_fp80, x86_fp80 }) align 16 initializes((0, 10), (16, 26)) [[AGG_RESULT:%.*]], ptr nocapture noundef readonly [[CLD:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-MINGW32: [[CLD_REAL:%.*]] = load x86_fp80, ptr [[CLD]], align 16 // CHECK-MINGW32: [[CLD_IMAG:%.*]] = load x86_fp80, ptr [[CLD_IMAGP:%.*]], align 16 // CHECK-MINGW32: store x86_fp80 [[CLD_REAL]], ptr [[BYVAL_TEMP:%.*]], align 16 diff --git a/clang/test/CodeGen/math-libcalls.c b/clang/test/CodeGen/math-libcalls.c index 2226212eca94ee81902574c602c1e142be3e10f5..bcc61c8f046b438a3e227d44ae3692350d64f1db 100644 --- a/clang/test/CodeGen/math-libcalls.c +++ b/clang/test/CodeGen/math-libcalls.c @@ -23,19 +23,19 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { atan2(f,f); atan2f(f,f) ; atan2l(f, f); - // NO__ERRNO: declare double @atan2(double noundef, double noundef) [[READNONE:#[0-9]+]] - // NO__ERRNO: declare float @atan2f(float noundef, float noundef) [[READNONE]] - // NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[READNONE]] + // NO__ERRNO: declare double @llvm.atan2.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] + // NO__ERRNO: declare float @llvm.atan2.f32(float, float) [[READNONE_INTRINSIC]] + // NO__ERRNO: declare x86_fp80 @llvm.atan2.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @atan2(double noundef, double noundef) [[NOT_READNONE]] // HAS_ERRNO: declare float @atan2f(float noundef, float noundef) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]] - // HAS_MAYTRAP: declare double @atan2(double noundef, double noundef) [[NOT_READNONE:#[0-9]+]] - // HAS_MAYTRAP: declare float @atan2f(float noundef, float noundef) [[NOT_READNONE]] - // HAS_MAYTRAP: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]] + // HAS_MAYTRAP: declare double @llvm.experimental.constrained.atan2.f64( + // HAS_MAYTRAP: declare float @llvm.experimental.constrained.atan2.f32( + // HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.atan2.f80( copysign(f,f); copysignf(f,f);copysignl(f,f); - // NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] + // NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] @@ -65,13 +65,13 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE]] // HAS_ERRNO: declare float @frexpf(float noundef, ptr noundef) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]] - // HAS_MAYTRAP: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE]] + // HAS_MAYTRAP: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE:#[0-9]+]] // HAS_MAYTRAP: declare float @frexpf(float noundef, ptr noundef) [[NOT_READNONE]] // HAS_MAYTRAP: declare x86_fp80 @frexpl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]] ldexp(f,f); ldexpf(f,f); ldexpl(f,f); - // NO__ERRNO: declare double @ldexp(double noundef, i32 noundef) [[READNONE]] + // NO__ERRNO: declare double @ldexp(double noundef, i32 noundef) [[READNONE:#[0-9]+]] // NO__ERRNO: declare float @ldexpf(float noundef, i32 noundef) [[READNONE]] // NO__ERRNO: declare x86_fp80 @ldexpl(x86_fp80 noundef, i32 noundef) [[READNONE]] // HAS_ERRNO: declare double @ldexp(double noundef, i32 noundef) [[NOT_READNONE]] @@ -719,9 +719,9 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare x86_fp80 @llvm.trunc.f80(x86_fp80) [[READNONE_INTRINSIC]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[READONLY]] = { {{.*}}memory(read){{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } diff --git a/clang/test/CodeGen/ms-mixed-ptr-sizes.c b/clang/test/CodeGen/ms-mixed-ptr-sizes.c index f99c6196557e1892544afc13c86f0ef90776f143..6ba315e165d3f10ff7da177776fc9b3713a37904 100644 --- a/clang/test/CodeGen/ms-mixed-ptr-sizes.c +++ b/clang/test/CodeGen/ms-mixed-ptr-sizes.c @@ -9,7 +9,7 @@ struct Foo { void use_foo(struct Foo *f); void test_sign_ext(struct Foo *f, int * __ptr32 __sptr i) { // X64-LABEL: define dso_local void @test_sign_ext({{.*}}ptr addrspace(270) noundef %i) -// X86-LABEL: define dso_local void @test_sign_ext(ptr noundef %f, ptr noundef %i) +// X86-LABEL: define dso_local void @test_sign_ext(ptr noundef initializes((8, 16)) %f, ptr noundef %i) // AARCH64-LABEL: define dso_local void @test_sign_ext({{.*}}ptr addrspace(270) noundef %i) local_unnamed_addr #0 // X64: %{{.+}} = addrspacecast ptr addrspace(270) %i to ptr // X86: %{{.+}} = addrspacecast ptr %i to ptr addrspace(272) @@ -18,9 +18,9 @@ void test_sign_ext(struct Foo *f, int * __ptr32 __sptr i) { use_foo(f); } void test_zero_ext(struct Foo *f, int * __ptr32 __uptr i) { -// X64-LABEL: define dso_local void @test_zero_ext({{.*}}ptr addrspace(271) noundef %i) +// X64-LABEL: define dso_local void @test_zero_ext(ptr noundef initializes((8, 16)) %f, ptr addrspace(271) noundef %i) // X86-LABEL: define dso_local void @test_zero_ext({{.*}}ptr addrspace(271) noundef %i) -// AARCH64-LABEL: define dso_local void @test_zero_ext({{.*}}ptr addrspace(271) noundef %i) local_unnamed_addr #0 +// AARCH64-LABEL: define dso_local void @test_zero_ext(ptr noundef initializes((8, 16)) %f, ptr addrspace(271) noundef %i) local_unnamed_addr #0 // X64: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr // X86: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr addrspace(272) // AARCH64: %{{.+}} = addrspacecast ptr addrspace(271) %i to ptr @@ -28,9 +28,9 @@ void test_zero_ext(struct Foo *f, int * __ptr32 __uptr i) { use_foo(f); } void test_trunc(struct Foo *f, int * __ptr64 i) { -// X64-LABEL: define dso_local void @test_trunc(ptr noundef %f, ptr noundef %i) +// X64-LABEL: define dso_local void @test_trunc(ptr noundef initializes((0, 4)) %f, ptr noundef %i) // X86-LABEL: define dso_local void @test_trunc({{.*}}ptr addrspace(272) noundef %i) -// AARCH64-LABEL: define dso_local void @test_trunc(ptr noundef %f, ptr noundef %i) local_unnamed_addr #0 +// AARCH64-LABEL: define dso_local void @test_trunc(ptr noundef initializes((0, 4)) %f, ptr noundef %i) local_unnamed_addr #0 // X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(270) // X86: %{{.+}} = addrspacecast ptr addrspace(272) %i to ptr // AARCH64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(270) diff --git a/clang/test/CodeGen/ptrauth-module-flags.c b/clang/test/CodeGen/ptrauth-module-flags.c new file mode 100644 index 0000000000000000000000000000000000000000..5a7e9a7c2a36fe923fd901b758a9f1a0a520766e --- /dev/null +++ b/clang/test/CodeGen/ptrauth-module-flags.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT + +// ELFGOT: !llvm.module.flags = !{ +// ELFGOT-SAME: !1 +// ELFGOT: !1 = !{i32 8, !"ptrauth-elf-got", i32 1} + +// OFF-NOT: "ptrauth- diff --git a/clang/test/CodeGen/scoped-fence-ops.c b/clang/test/CodeGen/scoped-fence-ops.c new file mode 100644 index 0000000000000000000000000000000000000000..376cb11e84d3da54e439ff7149bbcb1e6c84c63c --- /dev/null +++ b/clang/test/CodeGen/scoped-fence-ops.c @@ -0,0 +1,257 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=amdgcn-amd-amdhsa -ffreestanding \ +// RUN: -fvisibility=hidden | FileCheck --check-prefix=AMDGCN %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=spirv64-unknown-unknown -ffreestanding \ +// RUN: -fvisibility=hidden | FileCheck --check-prefix=SPIRV %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-unknown-linux-gnu -ffreestanding \ +// RUN: -fvisibility=hidden | FileCheck --check-prefix=X86_64 %s + +// AMDGCN-LABEL: define hidden void @fe1a( +// AMDGCN-SAME: ) #[[ATTR0:[0-9]+]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: fence syncscope("workgroup-one-as") release +// AMDGCN-NEXT: ret void +// +// SPIRV-LABEL: define hidden spir_func void @fe1a( +// SPIRV-SAME: ) #[[ATTR0:[0-9]+]] { +// SPIRV-NEXT: [[ENTRY:.*:]] +// SPIRV-NEXT: fence syncscope("workgroup") release +// SPIRV-NEXT: ret void +// +// X86_64-LABEL: define hidden void @fe1a( +// X86_64-SAME: ) #[[ATTR0:[0-9]+]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: fence release +// X86_64-NEXT: ret void +// +void fe1a() { + __scoped_atomic_thread_fence(__ATOMIC_RELEASE, __MEMORY_SCOPE_WRKGRP); +} + +// AMDGCN-LABEL: define hidden void @fe1b( +// AMDGCN-SAME: i32 noundef [[ORD:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: [[ORD_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// AMDGCN-NEXT: [[ORD_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[ORD_ADDR]] to ptr +// AMDGCN-NEXT: store i32 [[ORD]], ptr [[ORD_ADDR_ASCAST]], align 4 +// AMDGCN-NEXT: [[TMP0:%.*]] = load i32, ptr [[ORD_ADDR_ASCAST]], align 4 +// AMDGCN-NEXT: switch i32 [[TMP0]], label %[[ATOMIC_SCOPE_CONTINUE:.*]] [ +// AMDGCN-NEXT: i32 1, label %[[ACQUIRE:.*]] +// AMDGCN-NEXT: i32 2, label %[[ACQUIRE]] +// AMDGCN-NEXT: i32 3, label %[[RELEASE:.*]] +// AMDGCN-NEXT: i32 4, label %[[ACQREL:.*]] +// AMDGCN-NEXT: i32 5, label %[[SEQCST:.*]] +// AMDGCN-NEXT: ] +// AMDGCN: [[ATOMIC_SCOPE_CONTINUE]]: +// AMDGCN-NEXT: ret void +// AMDGCN: [[ACQUIRE]]: +// AMDGCN-NEXT: fence syncscope("workgroup-one-as") acquire +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[RELEASE]]: +// AMDGCN-NEXT: fence syncscope("workgroup-one-as") release +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[ACQREL]]: +// AMDGCN-NEXT: fence syncscope("workgroup-one-as") acq_rel +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[SEQCST]]: +// AMDGCN-NEXT: fence syncscope("workgroup") seq_cst +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// +// SPIRV-LABEL: define hidden spir_func void @fe1b( +// SPIRV-SAME: i32 noundef [[ORD:%.*]]) #[[ATTR0]] { +// SPIRV-NEXT: [[ENTRY:.*:]] +// SPIRV-NEXT: [[ORD_ADDR:%.*]] = alloca i32, align 4 +// SPIRV-NEXT: store i32 [[ORD]], ptr [[ORD_ADDR]], align 4 +// SPIRV-NEXT: [[TMP0:%.*]] = load i32, ptr [[ORD_ADDR]], align 4 +// SPIRV-NEXT: switch i32 [[TMP0]], label %[[ATOMIC_SCOPE_CONTINUE:.*]] [ +// SPIRV-NEXT: i32 1, label %[[ACQUIRE:.*]] +// SPIRV-NEXT: i32 2, label %[[ACQUIRE]] +// SPIRV-NEXT: i32 3, label %[[RELEASE:.*]] +// SPIRV-NEXT: i32 4, label %[[ACQREL:.*]] +// SPIRV-NEXT: i32 5, label %[[SEQCST:.*]] +// SPIRV-NEXT: ] +// SPIRV: [[ATOMIC_SCOPE_CONTINUE]]: +// SPIRV-NEXT: ret void +// SPIRV: [[ACQUIRE]]: +// SPIRV-NEXT: fence syncscope("workgroup") acquire +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[RELEASE]]: +// SPIRV-NEXT: fence syncscope("workgroup") release +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[ACQREL]]: +// SPIRV-NEXT: fence syncscope("workgroup") acq_rel +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[SEQCST]]: +// SPIRV-NEXT: fence syncscope("workgroup") seq_cst +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// +// X86_64-LABEL: define hidden void @fe1b( +// X86_64-SAME: i32 noundef [[ORD:%.*]]) #[[ATTR0]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: [[ORD_ADDR:%.*]] = alloca i32, align 4 +// X86_64-NEXT: store i32 [[ORD]], ptr [[ORD_ADDR]], align 4 +// X86_64-NEXT: [[TMP0:%.*]] = load i32, ptr [[ORD_ADDR]], align 4 +// X86_64-NEXT: switch i32 [[TMP0]], label %[[ATOMIC_SCOPE_CONTINUE:.*]] [ +// X86_64-NEXT: i32 1, label %[[ACQUIRE:.*]] +// X86_64-NEXT: i32 2, label %[[ACQUIRE]] +// X86_64-NEXT: i32 3, label %[[RELEASE:.*]] +// X86_64-NEXT: i32 4, label %[[ACQREL:.*]] +// X86_64-NEXT: i32 5, label %[[SEQCST:.*]] +// X86_64-NEXT: ] +// X86_64: [[ATOMIC_SCOPE_CONTINUE]]: +// X86_64-NEXT: ret void +// X86_64: [[ACQUIRE]]: +// X86_64-NEXT: fence acquire +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[RELEASE]]: +// X86_64-NEXT: fence release +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[ACQREL]]: +// X86_64-NEXT: fence acq_rel +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[SEQCST]]: +// X86_64-NEXT: fence seq_cst +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// +void fe1b(int ord) { + __scoped_atomic_thread_fence(ord, __MEMORY_SCOPE_WRKGRP); +} + +// AMDGCN-LABEL: define hidden void @fe1c( +// AMDGCN-SAME: i32 noundef [[SCOPE:%.*]]) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: [[SCOPE_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// AMDGCN-NEXT: [[SCOPE_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SCOPE_ADDR]] to ptr +// AMDGCN-NEXT: store i32 [[SCOPE]], ptr [[SCOPE_ADDR_ASCAST]], align 4 +// AMDGCN-NEXT: [[TMP0:%.*]] = load i32, ptr [[SCOPE_ADDR_ASCAST]], align 4 +// AMDGCN-NEXT: switch i32 [[TMP0]], label %[[ATOMIC_SCOPE_CONTINUE:.*]] [ +// AMDGCN-NEXT: i32 1, label %[[DEVICE_SCOPE:.*]] +// AMDGCN-NEXT: i32 0, label %[[SYSTEM_SCOPE:.*]] +// AMDGCN-NEXT: i32 2, label %[[WORKGROUP_SCOPE:.*]] +// AMDGCN-NEXT: i32 3, label %[[WAVEFRONT_SCOPE:.*]] +// AMDGCN-NEXT: i32 4, label %[[SINGLE_SCOPE:.*]] +// AMDGCN-NEXT: ] +// AMDGCN: [[ATOMIC_SCOPE_CONTINUE]]: +// AMDGCN-NEXT: ret void +// AMDGCN: [[DEVICE_SCOPE]]: +// AMDGCN-NEXT: fence syncscope("agent-one-as") release +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[SYSTEM_SCOPE]]: +// AMDGCN-NEXT: fence syncscope("one-as") release +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[WORKGROUP_SCOPE]]: +// AMDGCN-NEXT: fence syncscope("workgroup-one-as") release +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[WAVEFRONT_SCOPE]]: +// AMDGCN-NEXT: fence syncscope("wavefront-one-as") release +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// AMDGCN: [[SINGLE_SCOPE]]: +// AMDGCN-NEXT: fence syncscope("singlethread-one-as") release +// AMDGCN-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// +// SPIRV-LABEL: define hidden spir_func void @fe1c( +// SPIRV-SAME: i32 noundef [[SCOPE:%.*]]) #[[ATTR0]] { +// SPIRV-NEXT: [[ENTRY:.*:]] +// SPIRV-NEXT: [[SCOPE_ADDR:%.*]] = alloca i32, align 4 +// SPIRV-NEXT: store i32 [[SCOPE]], ptr [[SCOPE_ADDR]], align 4 +// SPIRV-NEXT: [[TMP0:%.*]] = load i32, ptr [[SCOPE_ADDR]], align 4 +// SPIRV-NEXT: switch i32 [[TMP0]], label %[[ATOMIC_SCOPE_CONTINUE:.*]] [ +// SPIRV-NEXT: i32 1, label %[[DEVICE_SCOPE:.*]] +// SPIRV-NEXT: i32 0, label %[[SYSTEM_SCOPE:.*]] +// SPIRV-NEXT: i32 2, label %[[WORKGROUP_SCOPE:.*]] +// SPIRV-NEXT: i32 3, label %[[WAVEFRONT_SCOPE:.*]] +// SPIRV-NEXT: i32 4, label %[[SINGLE_SCOPE:.*]] +// SPIRV-NEXT: ] +// SPIRV: [[ATOMIC_SCOPE_CONTINUE]]: +// SPIRV-NEXT: ret void +// SPIRV: [[DEVICE_SCOPE]]: +// SPIRV-NEXT: fence syncscope("device") release +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[SYSTEM_SCOPE]]: +// SPIRV-NEXT: fence release +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[WORKGROUP_SCOPE]]: +// SPIRV-NEXT: fence syncscope("workgroup") release +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[WAVEFRONT_SCOPE]]: +// SPIRV-NEXT: fence syncscope("subgroup") release +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// SPIRV: [[SINGLE_SCOPE]]: +// SPIRV-NEXT: fence syncscope("singlethread") release +// SPIRV-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// +// X86_64-LABEL: define hidden void @fe1c( +// X86_64-SAME: i32 noundef [[SCOPE:%.*]]) #[[ATTR0]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: [[SCOPE_ADDR:%.*]] = alloca i32, align 4 +// X86_64-NEXT: store i32 [[SCOPE]], ptr [[SCOPE_ADDR]], align 4 +// X86_64-NEXT: [[TMP0:%.*]] = load i32, ptr [[SCOPE_ADDR]], align 4 +// X86_64-NEXT: switch i32 [[TMP0]], label %[[ATOMIC_SCOPE_CONTINUE:.*]] [ +// X86_64-NEXT: i32 1, label %[[DEVICE_SCOPE:.*]] +// X86_64-NEXT: i32 0, label %[[SYSTEM_SCOPE:.*]] +// X86_64-NEXT: i32 2, label %[[WORKGROUP_SCOPE:.*]] +// X86_64-NEXT: i32 3, label %[[WAVEFRONT_SCOPE:.*]] +// X86_64-NEXT: i32 4, label %[[SINGLE_SCOPE:.*]] +// X86_64-NEXT: ] +// X86_64: [[ATOMIC_SCOPE_CONTINUE]]: +// X86_64-NEXT: ret void +// X86_64: [[DEVICE_SCOPE]]: +// X86_64-NEXT: fence release +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[SYSTEM_SCOPE]]: +// X86_64-NEXT: fence release +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[WORKGROUP_SCOPE]]: +// X86_64-NEXT: fence release +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[WAVEFRONT_SCOPE]]: +// X86_64-NEXT: fence release +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// X86_64: [[SINGLE_SCOPE]]: +// X86_64-NEXT: fence release +// X86_64-NEXT: br label %[[ATOMIC_SCOPE_CONTINUE]] +// +void fe1c(int scope) { + __scoped_atomic_thread_fence(__ATOMIC_RELEASE, scope); +} + +// AMDGCN-LABEL: define hidden void @fe2a( +// AMDGCN-SAME: ) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: ret void +// +// SPIRV-LABEL: define hidden spir_func void @fe2a( +// SPIRV-SAME: ) #[[ATTR0]] { +// SPIRV-NEXT: [[ENTRY:.*:]] +// SPIRV-NEXT: ret void +// +// X86_64-LABEL: define hidden void @fe2a( +// X86_64-SAME: ) #[[ATTR0]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: ret void +// +void fe2a() { + __scoped_atomic_thread_fence(999, __MEMORY_SCOPE_SYSTEM); +} + +// AMDGCN-LABEL: define hidden void @fe2b( +// AMDGCN-SAME: ) #[[ATTR0]] { +// AMDGCN-NEXT: [[ENTRY:.*:]] +// AMDGCN-NEXT: fence syncscope("one-as") release +// AMDGCN-NEXT: ret void +// +// SPIRV-LABEL: define hidden spir_func void @fe2b( +// SPIRV-SAME: ) #[[ATTR0]] { +// SPIRV-NEXT: [[ENTRY:.*:]] +// SPIRV-NEXT: fence release +// SPIRV-NEXT: ret void +// +// X86_64-LABEL: define hidden void @fe2b( +// X86_64-SAME: ) #[[ATTR0]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: fence release +// X86_64-NEXT: ret void +// +void fe2b() { + __scoped_atomic_thread_fence(__ATOMIC_RELEASE, 999); +} diff --git a/clang/test/CodeGen/target-addrspace.cpp b/clang/test/CodeGen/target-addrspace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9adf53611bc2422eb5522c8d9c01d24415731d45 --- /dev/null +++ b/clang/test/CodeGen/target-addrspace.cpp @@ -0,0 +1,140 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -emit-llvm \ +// RUN: -fvisibility=hidden -o - %s | FileCheck %s --check-prefix=NVPTX +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm \ +// RUN: -fvisibility=hidden -o - %s | FileCheck %s --check-prefix=AMDGPU + +// NVPTX-LABEL: define hidden void @_Z1fPv( +// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// NVPTX-NEXT: [[ENTRY:.*:]] +// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: ret void +// +// AMDGPU-LABEL: define hidden void @_Z1fPv( +// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0:[0-9]+]] { +// AMDGPU-NEXT: [[ENTRY:.*:]] +// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) +// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr +// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8 +// AMDGPU-NEXT: ret void +// +void f(void *p) {} + +// NVPTX-LABEL: define hidden void @_Z2p1Pv( +// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// NVPTX-NEXT: [[ENTRY:.*:]] +// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: call void @_Z1fPv(ptr noundef [[TMP0]]) #[[ATTR1:[0-9]+]] +// NVPTX-NEXT: ret void +// +// AMDGPU-LABEL: define hidden void @_Z2p1Pv( +// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// AMDGPU-NEXT: [[ENTRY:.*:]] +// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) +// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr +// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8 +// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8 +// AMDGPU-NEXT: call void @_Z1fPv(ptr noundef [[TMP0]]) #[[ATTR1:[0-9]+]] +// AMDGPU-NEXT: ret void +// +void p1(void [[clang::address_space(0)]] * p) { f(p); } +// NVPTX-LABEL: define hidden noundef ptr @_Z2p2PU3AS3v( +// NVPTX-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] { +// NVPTX-NEXT: [[ENTRY:.*:]] +// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 8 +// NVPTX-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr +// NVPTX-NEXT: ret ptr [[TMP1]] +// +// AMDGPU-LABEL: define hidden noundef ptr @_Z2p2PU3AS3v( +// AMDGPU-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] { +// AMDGPU-NEXT: [[ENTRY:.*:]] +// AMDGPU-NEXT: [[RETVAL:%.*]] = alloca ptr, align 8, addrspace(5) +// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) +// AMDGPU-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr +// AMDGPU-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR_ASCAST]], align 4 +// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR_ASCAST]], align 4 +// AMDGPU-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr +// AMDGPU-NEXT: ret ptr [[TMP1]] +// +void *p2(void [[clang::address_space(3)]] * p) { return p; } +// NVPTX-LABEL: define hidden noundef ptr @_Z2p3PU3AS3v( +// NVPTX-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] { +// NVPTX-NEXT: [[ENTRY:.*:]] +// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 8 +// NVPTX-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr +// NVPTX-NEXT: ret ptr [[TMP1]] +// +// AMDGPU-LABEL: define hidden noundef ptr @_Z2p3PU3AS3v( +// AMDGPU-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] { +// AMDGPU-NEXT: [[ENTRY:.*:]] +// AMDGPU-NEXT: [[RETVAL:%.*]] = alloca ptr, align 8, addrspace(5) +// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) +// AMDGPU-NEXT: [[RETVAL_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[RETVAL]] to ptr +// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr +// AMDGPU-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR_ASCAST]], align 4 +// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR_ASCAST]], align 4 +// AMDGPU-NEXT: [[TMP1:%.*]] = addrspacecast ptr addrspace(3) [[TMP0]] to ptr +// AMDGPU-NEXT: ret ptr [[TMP1]] +// +void *p3(void [[clang::address_space(3)]] * p) { return p; } + +struct S { + S() = default; + ~S() = default; + void foo() {} +}; + +S s1; +S [[clang::address_space(1)]] s2; +S [[clang::address_space(3)]] s3; + +template void foo(Ty *) {} + +// NVPTX-LABEL: define hidden void @_Z2t1Pv( +// NVPTX-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// NVPTX-NEXT: [[ENTRY:.*:]] +// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8 +// NVPTX-NEXT: store ptr [[P]], ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: call void @_Z3fooIvEvPT_(ptr noundef [[TMP0]]) #[[ATTR1]] +// NVPTX-NEXT: ret void +// +// AMDGPU-LABEL: define hidden void @_Z2t1Pv( +// AMDGPU-SAME: ptr noundef [[P:%.*]]) #[[ATTR0]] { +// AMDGPU-NEXT: [[ENTRY:.*:]] +// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) +// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr +// AMDGPU-NEXT: store ptr [[P]], ptr [[P_ADDR_ASCAST]], align 8 +// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P_ADDR_ASCAST]], align 8 +// AMDGPU-NEXT: call void @_Z3fooIvEvPT_(ptr noundef [[TMP0]]) #[[ATTR1]] +// AMDGPU-NEXT: ret void +// +void t1(void *p) { foo(p); } +// NVPTX-LABEL: define hidden void @_Z2t3PU3AS3v( +// NVPTX-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] { +// NVPTX-NEXT: [[ENTRY:.*:]] +// NVPTX-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 8 +// NVPTX-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR]], align 8 +// NVPTX-NEXT: call void @_Z3fooIU3AS3vEvPT_(ptr addrspace(3) noundef [[TMP0]]) #[[ATTR1]] +// NVPTX-NEXT: ret void +// +// AMDGPU-LABEL: define hidden void @_Z2t3PU3AS3v( +// AMDGPU-SAME: ptr addrspace(3) noundef [[P:%.*]]) #[[ATTR0]] { +// AMDGPU-NEXT: [[ENTRY:.*:]] +// AMDGPU-NEXT: [[P_ADDR:%.*]] = alloca ptr addrspace(3), align 4, addrspace(5) +// AMDGPU-NEXT: [[P_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[P_ADDR]] to ptr +// AMDGPU-NEXT: store ptr addrspace(3) [[P]], ptr [[P_ADDR_ASCAST]], align 4 +// AMDGPU-NEXT: [[TMP0:%.*]] = load ptr addrspace(3), ptr [[P_ADDR_ASCAST]], align 4 +// AMDGPU-NEXT: call void @_Z3fooIU3AS3vEvPT_(ptr addrspace(3) noundef [[TMP0]]) #[[ATTR1]] +// AMDGPU-NEXT: ret void +// +void t3(void [[clang::address_space(3)]] *p) { foo(p); } diff --git a/clang/test/CodeGen/target-builtin-noerror.c b/clang/test/CodeGen/target-builtin-noerror.c index 1e53621bc6b5ae45ab7129ac90b127bed10b5279..0bbd8c3e5ddd815e26f075abd05f5eddddfb1895 100644 --- a/clang/test/CodeGen/target-builtin-noerror.c +++ b/clang/test/CodeGen/target-builtin-noerror.c @@ -209,4 +209,5 @@ void verifycpustrings(void) { (void)__builtin_cpu_is("znver3"); (void)__builtin_cpu_is("znver4"); (void)__builtin_cpu_is("znver5"); + (void)__builtin_cpu_is("diamondrapids"); } diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c index f33281ada9903fbb9b09cc4dd0c22b64aac18e1b..9417a0e2f09e8ce521a785b578827d04d67971ed 100644 --- a/clang/test/CodeGen/tbaa-pointers.c +++ b/clang/test/CodeGen/tbaa-pointers.c @@ -186,6 +186,27 @@ void vla1(int n, int ptr[][n], int idx) { ptr[idx][0] = 0; } +typedef struct { + int i1; +} TypedefS; + +// FIXME: The !tbaa tag for unnamed structs doesn't account for compatible +// types in C. +void unamed_struct_typedef(TypedefS *ptr) { +// COMMON-LABEL: define void @unamed_struct_typedef( +// COMMON-SAME: ptr noundef [[PTRA:%.+]]) +// COMMON: [[PTR_ADDR:%.+]] = alloca ptr, align 8 +// DEFAULT-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// DEFAULT-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]] +// ENABLED-NEXT: store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF:!.+]] +// ENABLED-NEXT: [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF]] +// COMMON-NEXT: [[GEP:%.+]] = getelementptr inbounds nuw %struct.TypedefS, ptr [[L0]], i32 0, i32 0 +// COMMON-NEXT: store i32 0, ptr [[GEP]], align 4 +// COMMON-NEXT: ret void + + ptr->i1 = 0; +} + // ENABLED: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0} // ENABLED: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0} // DEFAULT: [[ANYPTR]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0} @@ -217,3 +238,5 @@ void vla1(int n, int ptr[][n], int idx) { // DEFAULT: [[S2_TY]] = !{!"S2", [[ANY_POINTER]], i64 0} // COMMON: [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0} // COMMON: [[INT_TY]] = !{!"int", [[CHAR]], i64 0} +// ENABLED: [[P1TYPEDEF]] = !{[[P1TYPEDEF_TY:!.+]], [[P1TYPEDEF_TY]], i64 0} +// ENABLED: [[P1TYPEDEF_TY]] = !{!"p1 _ZTS8TypedefS", [[ANY_POINTER]], i64 0} diff --git a/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp b/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp index e8bb46982537bb9b759c1fddccf302630f5e76f7..7173b6e8fbe2a19c11342dc52b6dc94b9ebc4fff 100644 --- a/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp +++ b/clang/test/CodeGen/tbaa-struct-bitfield-endianness.cpp @@ -16,7 +16,7 @@ struct NamedBitfields { }; // CHECK-LABEL: _Z4copyP14NamedBitfieldsS0_ -// CHECK-SAME: ptr nocapture noundef writeonly [[A1:%.*]], ptr nocapture noundef readonly [[A2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-SAME: ptr nocapture noundef writeonly initializes((0, 16)) [[A1:%.*]], ptr nocapture noundef readonly [[A2:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) [[A1]], ptr noundef nonnull align 8 dereferenceable(16) [[A2]], i64 16, i1 false), !tbaa.struct [[TBAA_STRUCT2:![0-9]+]] // CHECK-NEXT: ret void diff --git a/clang/test/CodeGen/union-tbaa1.c b/clang/test/CodeGen/union-tbaa1.c index a5faa8269aed698119a16ce9601181d999147c30..5263b1714c8c6edd4e02adbfb4fd1965f39dca38 100644 --- a/clang/test/CodeGen/union-tbaa1.c +++ b/clang/test/CodeGen/union-tbaa1.c @@ -8,7 +8,7 @@ typedef union __attribute__((aligned(4))) { void bar(vect32 p[][2]); // CHECK-LABEL: define dso_local void @fred -// CHECK-SAME: (i32 noundef [[NUM:%.*]], ptr nocapture noundef writeonly [[VEC:%.*]], ptr nocapture noundef readonly [[INDEX:%.*]], ptr nocapture noundef readonly [[ARR:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-SAME: (i32 noundef [[NUM:%.*]], ptr nocapture noundef writeonly initializes((0, 8)) [[VEC:%.*]], ptr nocapture noundef readonly [[INDEX:%.*]], ptr nocapture noundef readonly [[ARR:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP:%.*]] = alloca [4 x [2 x %union.vect32]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[TMP]]) #[[ATTR3:[0-9]+]] diff --git a/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu b/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu index b295bbbdaaf955ac87949e1fb90c74839e5d6b46..838bdda82572867630ad905f9c41198362898988 100644 --- a/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu +++ b/clang/test/CodeGenCUDA/amdgpu-kernel-arg-pointer-type.cu @@ -188,14 +188,14 @@ __global__ void kernel2(int &x) { // CHECK-SPIRV-NEXT: ret void // // OPT-LABEL: define dso_local amdgpu_kernel void @_Z7kernel3PU3AS2iPU3AS1i( -// OPT-SAME: ptr addrspace(2) nocapture noundef readonly [[X:%.*]], ptr addrspace(1) nocapture noundef writeonly [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// OPT-SAME: ptr addrspace(2) nocapture noundef readonly [[X:%.*]], ptr addrspace(1) nocapture noundef writeonly initializes((0, 4)) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { // OPT-NEXT: [[ENTRY:.*:]] // OPT-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[X]], align 4 // OPT-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[Y]], align 4 // OPT-NEXT: ret void // // OPT-SPIRV-LABEL: define spir_kernel void @_Z7kernel3PU3AS2iPU3AS1i( -// OPT-SPIRV-SAME: ptr addrspace(2) nocapture noundef readonly [[X:%.*]], ptr addrspace(1) nocapture noundef writeonly [[Y:%.*]]) local_unnamed_addr addrspace(4) #[[ATTR1:[0-9]+]] { +// OPT-SPIRV-SAME: ptr addrspace(2) nocapture noundef readonly [[X:%.*]], ptr addrspace(1) nocapture noundef writeonly initializes((0, 4)) [[Y:%.*]]) local_unnamed_addr addrspace(4) #[[ATTR1:[0-9]+]] { // OPT-SPIRV-NEXT: [[ENTRY:.*:]] // OPT-SPIRV-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(2) [[X]], align 4 // OPT-SPIRV-NEXT: store i32 [[TMP0]], ptr addrspace(1) [[Y]], align 4 diff --git a/clang/test/CodeGenCUDASPIRV/spirv-attrs.cu b/clang/test/CodeGenCUDASPIRV/spirv-attrs.cu new file mode 100644 index 0000000000000000000000000000000000000000..466aee00717a07fd38e73e24f98d37e6629549a6 --- /dev/null +++ b/clang/test/CodeGenCUDASPIRV/spirv-attrs.cu @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fcuda-is-device -triple spirv64 -o - -emit-llvm -x cuda %s | FileCheck %s +// RUN: %clang_cc1 -fcuda-is-device -triple spirv32 -o - -emit-llvm -x cuda %s | FileCheck %s + +#define __global__ __attribute__((global)) + +__attribute__((reqd_work_group_size(128, 1, 1))) +__global__ void reqd_work_group_size_128_1_1() {} + +__attribute__((work_group_size_hint(2, 2, 2))) +__global__ void work_group_size_hint_2_2_2() {} + +__attribute__((vec_type_hint(int))) +__global__ void vec_type_hint_int() {} + +__attribute__((intel_reqd_sub_group_size(64))) +__global__ void intel_reqd_sub_group_size_64() {} + +// CHECK: define spir_kernel void @_Z28reqd_work_group_size_128_1_1v() #[[ATTR:[0-9]+]] !reqd_work_group_size ![[WG_SIZE:[0-9]+]] +// CHECK: define spir_kernel void @_Z26work_group_size_hint_2_2_2v() #[[ATTR]] !work_group_size_hint ![[WG_HINT:[0-9]+]] +// CHECK: define spir_kernel void @_Z17vec_type_hint_intv() #[[ATTR]] !vec_type_hint ![[VEC_HINT:[0-9]+]] +// CHECK: define spir_kernel void @_Z28intel_reqd_sub_group_size_64v() #[[ATTR]] !intel_reqd_sub_group_size ![[SUB_GRP:[0-9]+]] + +// CHECK: attributes #[[ATTR]] = { {{.*}} } + +// CHECK: ![[WG_SIZE]] = !{i32 128, i32 1, i32 1} +// CHECK: ![[WG_HINT]] = !{i32 2, i32 2, i32 2} +// CHECK: ![[VEC_HINT]] = !{i32 undef, i32 1} +// CHECK: ![[SUB_GRP]] = !{i32 64} diff --git a/clang/test/CodeGenCXX/aarch64-sve-vector-conditional-op.cpp b/clang/test/CodeGenCXX/aarch64-sve-vector-conditional-op.cpp index 7e7eff3e02dca542af435c4de434c677d4557677..d6fa26bd3409948e3fe624df088b0da56a413d2c 100644 --- a/clang/test/CodeGenCXX/aarch64-sve-vector-conditional-op.cpp +++ b/clang/test/CodeGenCXX/aarch64-sve-vector-conditional-op.cpp @@ -164,10 +164,10 @@ svint32_t cond_i32_splat(svint32_t a) { // CHECK-LABEL: @_Z14cond_u32_splatu12__SVUint32_t( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CMP:%.*]] = icmp ult [[A:%.*]], shufflevector ( insertelement ( poison, i32 1, i64 0), poison, zeroinitializer) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult [[A:%.*]], splat (i32 1) // CHECK-NEXT: [[CONV:%.*]] = zext [[CMP]] to // CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne [[CONV]], zeroinitializer -// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select [[VECTOR_COND]], [[A]], shufflevector ( insertelement ( poison, i32 1, i64 0), poison, zeroinitializer) +// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select [[VECTOR_COND]], [[A]], splat (i32 1) // CHECK-NEXT: ret [[VECTOR_SELECT]] // svuint32_t cond_u32_splat(svuint32_t a) { @@ -188,10 +188,10 @@ svint64_t cond_i64_splat(svint64_t a) { // CHECK-LABEL: @_Z14cond_u64_splatu12__SVUint64_t( // CHECK-NEXT: entry: -// CHECK-NEXT: [[CMP:%.*]] = icmp ult [[A:%.*]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) +// CHECK-NEXT: [[CMP:%.*]] = icmp ult [[A:%.*]], splat (i64 1) // CHECK-NEXT: [[CONV:%.*]] = zext [[CMP]] to // CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne [[CONV]], zeroinitializer -// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select [[VECTOR_COND]], [[A]], shufflevector ( insertelement ( poison, i64 1, i64 0), poison, zeroinitializer) +// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select [[VECTOR_COND]], [[A]], splat (i64 1) // CHECK-NEXT: ret [[VECTOR_SELECT]] // svuint64_t cond_u64_splat(svuint64_t a) { diff --git a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp index 26760a90eb1c715c1a3c899dea3b17aba55f9096..0cdc3b32521ff3950f9a985e2b09bdc93bb75abf 100644 --- a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp @@ -129,7 +129,7 @@ void run_foo_tml() { // // // CHECK-LABEL: define dso_local noundef i32 @_Z7foo_ovli.default( -// CHECK-SAME: i32 noundef [[TMP0:%.*]]) #[[ATTR1]] { +// CHECK-SAME: i32 noundef [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[DOTADDR]], align 4 @@ -137,13 +137,13 @@ void run_foo_tml() { // // // CHECK-LABEL: define dso_local noundef i32 @_Z7foo_ovlv.default( -// CHECK-SAME: ) #[[ATTR1]] { +// CHECK-SAME: ) #[[ATTR2]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 2 // // // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIssE7foo_tmlEv._Mfrintts( -// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2:[0-9]+]] comdat { +// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3:[0-9]+]] comdat { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -152,7 +152,7 @@ void run_foo_tml() { // // // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIssE7foo_tmlEv._Msme-f64f64Mssbs( -// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3:[0-9]+]] comdat { +// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR4:[0-9]+]] comdat { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -161,7 +161,7 @@ void run_foo_tml() { // // // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIssE7foo_tmlEv.default( -// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR1]] comdat { +// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -192,7 +192,7 @@ void run_foo_tml() { // // // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIisE7foo_tmlEv._Mfrintts( -// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat { +// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -201,7 +201,7 @@ void run_foo_tml() { // // // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIisE7foo_tmlEv._Msme-f64f64Mssbs( -// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat { +// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR4]] comdat { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 @@ -210,7 +210,7 @@ void run_foo_tml() { // // // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIisE7foo_tmlEv.default( -// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR1]] comdat { +// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 diff --git a/clang/test/CodeGenCXX/attr-target-version.cpp b/clang/test/CodeGenCXX/attr-target-version.cpp index 4e45fb75c515837d8b5917c40bda0c81256d6585..0fd9bc33df80945ca175a444d9823466a63784c1 100644 --- a/clang/test/CodeGenCXX/attr-target-version.cpp +++ b/clang/test/CodeGenCXX/attr-target-version.cpp @@ -220,7 +220,7 @@ int bar() { // // // CHECK-LABEL: define dso_local noundef i32 @_Z3barv( -// CHECK-SAME: ) #[[ATTR1]] { +// CHECK-SAME: ) #[[ATTR11:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[M:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1 // CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN7MyClass3gooEi(ptr noundef nonnull align 1 dereferenceable(1) [[M]], i32 noundef 1) diff --git a/clang/test/CodeGenCXX/auto-var-init-attr.cpp b/clang/test/CodeGenCXX/auto-var-init-attr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5481c6e8613c568201a931a01016cb474af24c8c --- /dev/null +++ b/clang/test/CodeGenCXX/auto-var-init-attr.cpp @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -fdeclspec -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s + +struct S { char c; }; +class C { char c; }; +enum class E { ZERO }; +union U { char c; int i; }; + +struct __declspec(no_init_all) NoInitS { char c; }; +class __declspec(no_init_all) NoInitC { char c; }; +enum class __declspec(no_init_all) NoInitE { ZERO }; +union __declspec(no_init_all) NoInitU { char c; int i; }; + +extern "C" { + void test_no_attr() { + // CHECK-LABEL: @test_no_attr() + // CHECK-NEXT: entry: + // CHECK-NEXT: %s = alloca %struct.S, align 1 + // CHECK-NEXT: %c = alloca %class.C, align 1 + // CHECK-NEXT: %e = alloca i32, align 4 + // CHECK-NEXT: %u = alloca %union.U, align 4 + // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 %s, i8 0, i64 1, i1 false) + // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 %c, i8 0, i64 1, i1 false) + // CHECK-NEXT: store i32 0, ptr %e, align 4 + // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 %u, i8 0, i64 4, i1 false) + // CHECK-NEXT ret void + S s; + C c; + E e; + U u; + } + + void __declspec(no_init_all) test_attr_on_function() { + // CHECK-LABEL: @test_attr_on_function() + // CHECK-NEXT: entry: + // CHECK-NEXT: %s = alloca %struct.S, align 1 + // CHECK-NEXT: %c = alloca %class.C, align 1 + // CHECK-NEXT: %e = alloca i32, align 4 + // CHECK-NEXT: %u = alloca %union.U, align 4 + // CHECK-NEXT: ret void + S s; + C c; + E e; + U u; + } + + void test_attr_on_decl() { + // CHECK-LABEL: @test_attr_on_decl() + // CHECK-NEXT: entry: + // CHECK-NEXT: %s = alloca %struct.NoInitS, align 1 + // CHECK-NEXT: %c = alloca %class.NoInitC, align 1 + // CHECK-NEXT: %e = alloca i32, align 4 + // CHECK-NEXT: %u = alloca %union.NoInitU, align 4 + // CHECK-NEXT: ret void + NoInitS s; + NoInitC c; + NoInitE e; + NoInitU u; + } +} \ No newline at end of file diff --git a/clang/test/CodeGenCXX/builtin-calling-conv.cpp b/clang/test/CodeGenCXX/builtin-calling-conv.cpp index 7020d1e0a24144074e24809de51ed82134693138..92d698b43be0ab5b14b8b31aebff625b921d3c59 100644 --- a/clang/test/CodeGenCXX/builtin-calling-conv.cpp +++ b/clang/test/CodeGenCXX/builtin-calling-conv.cpp @@ -13,7 +13,7 @@ using size_t = unsigned long; #endif // SPIR } // namespace std -float __builtin_atan2f(float, float); +float __builtin_erff(float); void *operator new(std::size_t); #endif // REDECL @@ -22,32 +22,32 @@ void foo(); void user() { int i; ::operator new(5); - (void)__builtin_atan2f(1.1, 2.2); + (void)__builtin_erff(1.1); foo(); } // LINUX: define{{.*}} void @_Z4userv() // LINUX: call noalias noundef nonnull ptr @_Znwm -// LINUX: call float @atan2f +// LINUX: call float @erff // LINUX: call void @_Z3foov // LINUX: declare noundef nonnull ptr @_Znwm(i64 noundef) -// LINUX: declare float @atan2f(float noundef, float noundef) +// LINUX: declare float @erff(float noundef) // LINUX: declare void @_Z3foov() // SPIR: define{{.*}} spir_func void @_Z4userv() // SPIR: call spir_func noalias noundef nonnull ptr @_Znwj -// SPIR: call spir_func float @atan2f +// SPIR: call spir_func float @erff // SPIR: call spir_func void @_Z3foov // SPIR: declare spir_func noundef nonnull ptr @_Znwj(i32 noundef) -// SPIR: declare spir_func float @atan2f(float noundef, float noundef) +// SPIR: declare spir_func float @erff(float noundef) // SPIR: declare spir_func void @_Z3foov() // Note: Windows /G options should not change the platform default calling // convention of builtins. // WIN32: define dso_local x86_stdcallcc void @"?user@@YGXXZ"() // WIN32: call noalias noundef nonnull ptr @"??2@YAPAXI@Z" -// WIN32: call float @atan2f +// WIN32: call float @erff // WIN32: call x86_stdcallcc void @"?foo@@YGXXZ" // WIN32: declare dso_local noundef nonnull ptr @"??2@YAPAXI@Z"( -// WIN32: declare dso_local float @atan2f(float noundef, float noundef) +// WIN32: declare dso_local float @erff(float noundef) // WIN32: declare dso_local x86_stdcallcc void @"?foo@@YGXXZ"() diff --git a/clang/test/CodeGenCXX/fmv-namespace.cpp b/clang/test/CodeGenCXX/fmv-namespace.cpp index c2346bdc1d68b2c6d97fa67864be0d33f3e81de9..d61f6dc9a7071b7b8e76e5feda933c9cd9115430 100644 --- a/clang/test/CodeGenCXX/fmv-namespace.cpp +++ b/clang/test/CodeGenCXX/fmv-namespace.cpp @@ -55,19 +55,19 @@ __attribute((target_version("mops"))) int bar() { return 1; } // // // CHECK-LABEL: define dso_local noundef i32 @_ZN3Foo3barEv.default( -// CHECK-SAME: ) #[[ATTR1]] { +// CHECK-SAME: ) #[[ATTR3:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 0 // // // CHECK-LABEL: define dso_local noundef i32 @_ZN3Foo3barEv._Mmops( -// CHECK-SAME: ) #[[ATTR3:[0-9]+]] { +// CHECK-SAME: ) #[[ATTR4:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 1 // // // CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv.default( -// CHECK-SAME: ) #[[ATTR1]] { +// CHECK-SAME: ) #[[ATTR3]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: ret i32 0 // diff --git a/clang/test/CodeGenCXX/inline-then-fold-variadics.cpp b/clang/test/CodeGenCXX/inline-then-fold-variadics.cpp index a0673b96626d15e9173d0490c5ff1f55d584c1a6..4aa79a28dd7d3d0a6e060a1d8b96d8e72b065bc3 100644 --- a/clang/test/CodeGenCXX/inline-then-fold-variadics.cpp +++ b/clang/test/CodeGenCXX/inline-then-fold-variadics.cpp @@ -108,7 +108,7 @@ typedef uint64_t ulong2 __attribute__((__vector_size__(16), __aligned__(16))); int first_i32_ulong2(int x, ulong2 *y) { return first(x, *y); } // CHECK-LABEL: define {{[^@]+}}@second_i32_ulong2 -// CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[Y]], align 16, !tbaa [[TBAA2:![0-9]+]] // CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]] @@ -119,7 +119,7 @@ void second_i32_ulong2(int x, ulong2 *y, ulong2 *r) { } // CHECK-LABEL: define {{[^@]+}}@first_ulong2_i32 -// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[X]], align 16, !tbaa [[TBAA2]] // CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]] @@ -157,7 +157,7 @@ extern "C" { int first_i32_asc(int x, asc *y) { return first(x, *y); } // CHECK-LABEL: define {{[^@]+}}@second_i32_asc -// CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-NEXT: entry: // CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[Y]], i32 24, i1 false) // CHECK-NEXT: ret void @@ -165,7 +165,7 @@ int first_i32_asc(int x, asc *y) { return first(x, *y); } void second_i32_asc(int x, asc *y, asc *r) { *r = second(x, *y); } // CHECK-LABEL: define {{[^@]+}}@first_asc_i32 -// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] { // CHECK-NEXT: entry: // CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[X]], i32 24, i1 false) // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp b/clang/test/CodeGenCXX/ms-thread_local.cpp index cb0e8720c19b8b742634133a5bc290678320b632..1e1d1db0744b295fece14cd3b916119dac47f583 100644 --- a/clang/test/CodeGenCXX/ms-thread_local.cpp +++ b/clang/test/CodeGenCXX/ms-thread_local.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LEGACY +// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.25 -fno-ms-tls-guards -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-NO-GUARDS // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 -fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD struct A { @@ -23,17 +24,20 @@ thread_local A a = A(); // CHECK-LD-DAG: @"__tls_init$initializer$" = internal constant ptr @__tls_init, section ".CRT$XDU" // CHECK-LD-DAG: @__tls_guard = external dso_local thread_local global i8 // CHECK-LEGACY-NOT: @__tls_guard = external dso_local thread_local global i8 +// CHECK-NO-GUARDS-NOT: @__tls_guard = external dso_local thread_local global i8 thread_local A b; // CHECK-LABEL: declare dso_local void @__dyn_tls_on_demand_init() // CHECK-LD-LABEL: declare dso_local void @__dyn_tls_on_demand_init() // CHECK-LEGACY-NOT: declare dso_local void @__dyn_tls_on_demand_init() +// CHECK-NO-GUARDS-NOT: declare dso_local void @__dyn_tls_on_demand_init() // CHECK-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result) // CHECK: call void @__dyn_tls_on_demand_init() // CHECK-LD-LABEL: define dso_local void @"?f@@YA?AUA@@XZ"(ptr dead_on_unwind noalias writable sret(%struct.A) align 1 %agg.result) // CHECK-LD: call void @__dyn_tls_on_demand_init() // CHECK-LEGACY-NOT: call void @__dyn_tls_on_demand_init() +// CHECK-NO-GUARDS-NOT: call void @__dyn_tls_on_demand_init() thread_local A &c = b; thread_local A &d = c; diff --git a/clang/test/CodeGenCXX/wasm-args-returns.cpp b/clang/test/CodeGenCXX/wasm-args-returns.cpp index e80dfefedece16862c8303c90c84060d8ccd6efe..b57896b0e0ffe779c830ec8830f6e33d0f9a952d 100644 --- a/clang/test/CodeGenCXX/wasm-args-returns.cpp +++ b/clang/test/CodeGenCXX/wasm-args-returns.cpp @@ -30,7 +30,7 @@ struct two_fields { double d, e; }; test(two_fields); -// CHECK: define void @_Z7forward10two_fields(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.two_fields) align 8 %{{.*}}, ptr nocapture readonly byval(%struct.two_fields) align 8 %{{.*}}) +// CHECK: define void @_Z7forward10two_fields(ptr dead_on_unwind noalias nocapture writable writeonly sret(%struct.two_fields) align 8 initializes((0, 16)) %{{.*}}, ptr nocapture readonly byval(%struct.two_fields) align 8 %{{.*}}) // // CHECK: define void @_Z15test_two_fieldsv() // CHECK: %[[tmp:.*]] = alloca %struct.two_fields, align 8 diff --git a/clang/test/CodeGenHLSL/builtins/clip.hlsl b/clang/test/CodeGenHLSL/builtins/clip.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..63843c151e3ac56b9813ba22aedc9a4a436c9cf1 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clip.hlsl @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple spirv-vulkan-pixel %s -fnative-half-type -emit-llvm -o - | FileCheck %s --check-prefix=SPIRV + + +void test_scalar(float Buf) { + // CHECK: define void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]]) + // CHECK: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4 + // CHECK-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00 + // CHECK-NO: call i1 @llvm.dx.any + // CHECK-NEXT: call void @llvm.dx.discard(i1 [[FCMP]]) + // + // SPIRV: define spir_func void @{{.*}}test_scalar{{.*}}(float {{.*}} [[VALP:%.*]]) + // SPIRV: [[LOAD:%.*]] = load float, ptr [[VALP]].addr, align 4 + // SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt float [[LOAD]], 0.000000e+00 + // SPIRV-NO: call i1 @llvm.spv.any + // SPIRV-NEXT: br i1 [[FCMP]], label %[[LTL:.*]], label %[[ENDL:.*]] + // SPIRV: [[LTL]]: ; preds = %entry + // SPIRV-NEXT: call void @llvm.spv.discard() + // SPIRV: br label %[[ENDL]] + clip(Buf); +} + +void test_vector4(float4 Buf) { + // CHECK: define void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]]) + // CHECK: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16 + // CHECK-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer + // CHECK-NEXT: [[ANYC:%.*]] = call i1 @llvm.dx.any.v4i1(<4 x i1> [[FCMP]]) + // CHECK-NEXT: call void @llvm.dx.discard(i1 [[ANYC]]) + // + // SPIRV: define spir_func void @{{.*}}test_vector{{.*}}(<4 x float> {{.*}} [[VALP:%.*]]) + // SPIRV: [[LOAD:%.*]] = load <4 x float>, ptr [[VALP]].addr, align 16 + // SPIRV-NEXT: [[FCMP:%.*]] = fcmp olt <4 x float> [[LOAD]], zeroinitializer + // SPIRV-NEXT: [[ANYC:%.*]] = call i1 @llvm.spv.any.v4i1(<4 x i1> [[FCMP]]) + // SPIRV-NEXT: br i1 [[ANYC]], label %[[LTL:.*]], label %[[ENDL:.*]] + // SPIRV: [[LTL]]: ; preds = %entry + // SPIRV-NEXT: call void @llvm.spv.discard() + // SPIRV-NEXT: br label %[[ENDL]] + clip(Buf); +} diff --git a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl index 5cb8af6fc6df9c84b1ece247d196425a9e366965..35a08a90d8cf907d686c7821c7c0887d47c7f5f9 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl @@ -402,14 +402,14 @@ struct_arr16 func_ret_struct_arr16() return s; } -// CHECK: define{{.*}} void @func_ret_struct_arr32(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.struct_arr32) align 4 %agg.result) +// CHECK: define{{.*}} void @func_ret_struct_arr32(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.struct_arr32) align 4 initializes((0, 128)) %agg.result) struct_arr32 func_ret_struct_arr32() { struct_arr32 s = { 0 }; return s; } -// CHECK: define{{.*}} void @func_ret_struct_arr33(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.struct_arr33) align 4 %agg.result) +// CHECK: define{{.*}} void @func_ret_struct_arr33(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.struct_arr33) align 4 initializes((0, 132)) %agg.result) struct_arr33 func_ret_struct_arr33() { struct_arr33 s = { 0 }; @@ -438,7 +438,7 @@ different_size_type_pair func_different_size_type_pair_ret() return s; } -// CHECK: define{{.*}} void @func_flexible_array_ret(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.flexible_array) align 4 %agg.result) +// CHECK: define{{.*}} void @func_flexible_array_ret(ptr addrspace(5) dead_on_unwind noalias nocapture writable writeonly sret(%struct.flexible_array) align 4 initializes((0, 4)) %agg.result) flexible_array func_flexible_array_ret() { flexible_array s = { 0 }; @@ -467,7 +467,7 @@ double_nested_struct func_double_nested_struct_ret(int4 arg0, int arg1) { // CHECK: define{{.*}} void @func_large_struct_padding_arg_direct(i8 %arg.coerce0, i32 %arg.coerce1, i8 %arg.coerce2, i32 %arg.coerce3, i8 %arg.coerce4, i8 %arg.coerce5, i16 %arg.coerce6, i16 %arg.coerce7, [3 x i8] %arg.coerce8, i64 %arg.coerce9, i32 %arg.coerce10, i8 %arg.coerce11, i32 %arg.coerce12, i16 %arg.coerce13, i8 %arg.coerce14) void func_large_struct_padding_arg_direct(large_struct_padding arg) { } -// CHECK: define{{.*}} void @func_large_struct_padding_arg_store(ptr addrspace(1) nocapture noundef writeonly %out, ptr addrspace(5) nocapture noundef readonly byref(%struct.large_struct_padding) align 8 %{{.*}}) +// CHECK: define{{.*}} void @func_large_struct_padding_arg_store(ptr addrspace(1) nocapture noundef writeonly initializes((0, 56)) %out, ptr addrspace(5) nocapture noundef readonly byref(%struct.large_struct_padding) align 8 %{{.*}}) void func_large_struct_padding_arg_store(global large_struct_padding* out, large_struct_padding arg) { *out = arg; } diff --git a/clang/test/CodeGenOpenCL/amdgpu-call-kernel.cl b/clang/test/CodeGenOpenCL/amdgpu-call-kernel.cl index e4678abf3350099d9b64bd76c60dc81881b196a0..dfca09d034cdb1dbfe2ce921c8335754662d4167 100755 --- a/clang/test/CodeGenOpenCL/amdgpu-call-kernel.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-call-kernel.cl @@ -1,6 +1,6 @@ // REQUIRES: amdgpu-registered-target // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -emit-llvm -o - %s | FileCheck %s -// CHECK: define{{.*}} amdgpu_kernel void @test_call_kernel(ptr addrspace(1) nocapture noundef writeonly align 4 %out) +// CHECK: define{{.*}} amdgpu_kernel void @test_call_kernel(ptr addrspace(1) nocapture noundef writeonly align 4 initializes((0, 4)) %out) // CHECK: store i32 4, ptr addrspace(1) %out, align 4 kernel void test_kernel(global int *out) diff --git a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl index 2fc7f9a24b8874b6f110e3b0dcf0b546aa105904..62b5661da9dbd8c0643ef23dc6c5e93086cd3634 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl @@ -140,7 +140,7 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 4 // NOCPU-NEXT: [[TMP3:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1 // NOCPU-NEXT: store i8 [[TMP3]], ptr [[BLOCK_CAPTURED1]], align 8 -// NOCPU-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) +// NOCPU-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) // NOCPU-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 // NOCPU-NEXT: [[TMP6:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 // NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) @@ -162,7 +162,7 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[BLOCK_CAPTURED10:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 5 // NOCPU-NEXT: [[TMP10:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8 // NOCPU-NEXT: store i64 [[TMP10]], ptr [[BLOCK_CAPTURED10]], align 8 -// NOCPU-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) +// NOCPU-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) // NOCPU-NEXT: [[TMP12:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 // NOCPU-NEXT: [[TMP13:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 // NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP11_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) @@ -204,7 +204,7 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[TMP23:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 // NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP27_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) // NOCPU-NEXT: [[TMP24:%.*]] = load ptr, ptr [[BLOCK20_ASCAST]], align 8 -// NOCPU-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) +// NOCPU-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) // NOCPU-NEXT: ret void // // @@ -365,7 +365,7 @@ kernel void test_target_features_kernel(global int *i) { // NOCPU-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8 // NOCPU-NEXT: [[TMP2:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4 // NOCPU-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false) -// NOCPU-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) +// NOCPU-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) // NOCPU-NEXT: ret void // // @@ -486,7 +486,7 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK_CAPTURED1:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), i8 }>, ptr [[BLOCK_ASCAST]], i32 0, i32 4 // GFX900-NEXT: [[TMP3:%.*]] = load i8, ptr [[B_ADDR_ASCAST]], align 1, !tbaa [[TBAA13]] // GFX900-NEXT: store i8 [[TMP3]], ptr [[BLOCK_CAPTURED1]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) +// GFX900-NEXT: [[TMP4:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP0]], i32 [[TMP1]], ptr [[TMP_ASCAST]], ptr @__test_block_invoke_kernel, ptr [[BLOCK_ASCAST]]) // GFX900-NEXT: [[TMP5:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[TMP6:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] // GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP2_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] @@ -508,7 +508,7 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[BLOCK_CAPTURED10:%.*]] = getelementptr inbounds nuw <{ i32, i32, ptr, ptr addrspace(1), ptr addrspace(1), i64, i8 }>, ptr [[BLOCK3_ASCAST]], i32 0, i32 5 // GFX900-NEXT: [[TMP10:%.*]] = load i64, ptr [[D_ADDR_ASCAST]], align 8, !tbaa [[TBAA3]] // GFX900-NEXT: store i64 [[TMP10]], ptr [[BLOCK_CAPTURED10]], align 8, !tbaa [[TBAA3]] -// GFX900-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) +// GFX900-NEXT: [[TMP11:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP5]], i32 [[TMP6]], ptr [[TMP2_ASCAST]], ptr @__test_block_invoke_2_kernel, ptr [[BLOCK3_ASCAST]]) // GFX900-NEXT: [[TMP12:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[TMP13:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] // GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP11_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] @@ -553,7 +553,7 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[TMP23:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] // GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP27_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] // GFX900-NEXT: [[TMP24:%.*]] = load ptr, ptr [[BLOCK20_ASCAST]], align 8, !tbaa [[TBAA13]] -// GFX900-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) +// GFX900-NEXT: [[TMP25:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP22]], i32 [[TMP23]], ptr [[TMP27_ASCAST]], ptr @__test_block_invoke_4_kernel, ptr [[BLOCK21_ASCAST]]) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[BLOCK20]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] @@ -709,7 +709,7 @@ kernel void test_target_features_kernel(global int *i) { // GFX900-NEXT: [[TMP1:%.*]] = load ptr addrspace(1), ptr [[DEFAULT_QUEUE_ASCAST]], align 8, !tbaa [[TBAA16]] // GFX900-NEXT: [[TMP2:%.*]] = load i32, ptr [[FLAGS_ASCAST]], align 4, !tbaa [[TBAA14]] // GFX900-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP_ASCAST]], ptr align 4 [[NDRANGE_ASCAST]], i64 4, i1 false), !tbaa.struct [[TBAA_STRUCT18]] -// GFX900-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) +// GFX900-NEXT: [[TMP3:%.*]] = call i32 @__enqueue_kernel_basic(ptr addrspace(1) [[TMP1]], i32 [[TMP2]], ptr [[TMP_ASCAST]], ptr @__test_target_features_kernel_block_invoke_kernel, ptr addrspacecast (ptr addrspace(1) @__block_literal_global to ptr)) // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[NDRANGE]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[FLAGS]]) #[[ATTR8]] // GFX900-NEXT: call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[DEFAULT_QUEUE]]) #[[ATTR8]] diff --git a/clang/test/CodeGenOpenCL/amdgpu-features.cl b/clang/test/CodeGenOpenCL/amdgpu-features.cl index f3473346baae5a674dc13bf45fb8fccf0215ae57..61cbf5e65d0d2151c93f901aea6fc656c84ea061 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-features.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-features.cl @@ -32,6 +32,7 @@ // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx940 -emit-llvm -o - %s | FileCheck --check-prefix=GFX940 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx941 -emit-llvm -o - %s | FileCheck --check-prefix=GFX941 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx942 -emit-llvm -o - %s | FileCheck --check-prefix=GFX942 %s +// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx950 -emit-llvm -o - %s | FileCheck --check-prefix=GFX950 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1010 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1010 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1011 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1011 %s // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1012 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1012 %s @@ -56,6 +57,8 @@ // RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1103 -target-feature +wavefrontsize64 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1103-W64 %s +// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx9-4-generic -emit-llvm -o - %s | FileCheck --check-prefix=GFX9_4_Generic %s + // NOCPU-NOT: "target-features" // NOCPU-WAVE32: "target-features"="+wavefrontsize32" // NOCPU-WAVE64: "target-features"="+wavefrontsize64" @@ -82,9 +85,11 @@ // GFX909: "target-features"="+16-bit-insts,+ci-insts,+dpp,+gfx8-insts,+gfx9-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" // GFX90A: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" // GFX90C: "target-features"="+16-bit-insts,+ci-insts,+dpp,+gfx8-insts,+gfx9-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" -// GFX940: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" -// GFX941: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" -// GFX942: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" +// GFX940: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64,+xf32-insts" +// GFX941: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64,+xf32-insts" +// GFX942: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64,+xf32-insts" +// GFX9_4_Generic: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" +// GFX950: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+fp8-conversion-insts,+fp8-insts,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gfx940-insts,+gfx950-insts,+mai-insts,+prng-inst,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" // GFX1010: "target-features"="+16-bit-insts,+ci-insts,+dl-insts,+dpp,+gfx10-insts,+gfx8-insts,+gfx9-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize32" // GFX1011: "target-features"="+16-bit-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx10-insts,+gfx8-insts,+gfx9-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize32" // GFX1012: "target-features"="+16-bit-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx10-insts,+gfx8-insts,+gfx9-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize32" diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx9-4-generic-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx9-4-generic-err.cl new file mode 100644 index 0000000000000000000000000000000000000000..dbeb8a6f2c16647e9105da1454255d9119b131b4 --- /dev/null +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx9-4-generic-err.cl @@ -0,0 +1,38 @@ +// REQUIRES: amdgpu-registered-target + +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -target-cpu gfx9-4-generic -verify -emit-llvm -o - %s + +typedef unsigned int uint; +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float4 __attribute__((ext_vector_type(4))); +typedef float float16 __attribute__((ext_vector_type(16))); +typedef int int2 __attribute__((ext_vector_type(2))); +typedef int int4 __attribute__((ext_vector_type(4))); + +void builtin_test_unsupported(uint a, uint b, int a_int, long a_long, float a_float, float b_float, + int2 a_int2, int4 a_int4, float2 a_float2, float4 a_float4, float16 a_float16) { + a_float4 = __builtin_amdgcn_mfma_f32_16x16x32_bf8_bf8(a_long, a_long, a_float4, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_16x16x32_bf8_bf8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_mfma_f32_16x16x32_bf8_fp8(a_long, a_long, a_float4, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_16x16x32_bf8_fp8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_mfma_f32_16x16x32_fp8_bf8(a_long, a_long, a_float4, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_16x16x32_fp8_bf8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_mfma_f32_16x16x32_fp8_fp8(a_long, a_long, a_float4, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_16x16x32_fp8_fp8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_mfma_f32_32x32x16_bf8_bf8(a_long, a_long, a_float16, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_32x32x16_bf8_bf8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_mfma_f32_32x32x16_bf8_fp8(a_long, a_long, a_float16, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_32x32x16_bf8_fp8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_mfma_f32_32x32x16_fp8_bf8(a_long, a_long, a_float16, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_32x32x16_fp8_bf8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_mfma_f32_32x32x16_fp8_fp8(a_long, a_long, a_float16, 0, 0, 0); // expected-error {{'__builtin_amdgcn_mfma_f32_32x32x16_fp8_fp8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_smfmac_f32_16x16x64_bf8_bf8(a_int2, a_int4, a_float4, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_16x16x64_bf8_bf8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_smfmac_f32_16x16x64_bf8_fp8(a_int2, a_int4, a_float4, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_16x16x64_bf8_fp8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_smfmac_f32_16x16x64_fp8_bf8(a_int2, a_int4, a_float4, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_16x16x64_fp8_bf8' needs target feature fp8-insts}} + a_float4 = __builtin_amdgcn_smfmac_f32_16x16x64_fp8_fp8(a_int2, a_int4, a_float4, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_16x16x64_fp8_fp8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_smfmac_f32_32x32x32_bf8_bf8(a_int2, a_int4, a_float16, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_32x32x32_bf8_bf8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_smfmac_f32_32x32x32_bf8_fp8(a_int2, a_int4, a_float16, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_32x32x32_bf8_fp8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_smfmac_f32_32x32x32_fp8_bf8(a_int2, a_int4, a_float16, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_32x32x32_fp8_bf8' needs target feature fp8-insts}} + a_float16 = __builtin_amdgcn_smfmac_f32_32x32x32_fp8_fp8(a_int2, a_int4, a_float16, a_int, 0, 0); // expected-error {{'__builtin_amdgcn_smfmac_f32_32x32x32_fp8_fp8' needs target feature fp8-insts}} + b = __builtin_amdgcn_cvt_f32_bf8(a, 0); // expected-error {{'__builtin_amdgcn_cvt_f32_bf8' needs target feature fp8-conversion-insts}} + b = __builtin_amdgcn_cvt_f32_fp8(a, 1); // expected-error {{'__builtin_amdgcn_cvt_f32_fp8' needs target feature fp8-conversion-insts}} + a_float2 = __builtin_amdgcn_cvt_pk_f32_bf8(a, false); // expected-error {{'__builtin_amdgcn_cvt_pk_f32_bf8' needs target feature fp8-conversion-insts}} + a_float2 = __builtin_amdgcn_cvt_pk_f32_fp8(a, true); // expected-error {{'__builtin_amdgcn_cvt_pk_f32_fp8' needs target feature fp8-conversion-insts}} + b = __builtin_amdgcn_cvt_pk_bf8_f32(a_float, b_float, a, false); // expected-error {{'__builtin_amdgcn_cvt_pk_bf8_f32' needs target feature fp8-conversion-insts}} + b = __builtin_amdgcn_cvt_pk_fp8_f32(a_float, b_float, a, true); // expected-error {{'__builtin_amdgcn_cvt_pk_fp8_f32' needs target feature fp8-conversion-insts}} + b = __builtin_amdgcn_cvt_sr_bf8_f32(a_float, b_float, a, 2); // expected-error {{'__builtin_amdgcn_cvt_sr_bf8_f32' needs target feature fp8-conversion-insts}} + b = __builtin_amdgcn_cvt_sr_fp8_f32(a_float, b_float, a, 3); // expected-error {{'__builtin_amdgcn_cvt_sr_fp8_f32' needs target feature fp8-conversion-insts}} +} diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950-err.cl new file mode 100644 index 0000000000000000000000000000000000000000..86f4f73c81c0fc4cce89b2392c6e03b19a9e0093 --- /dev/null +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950-err.cl @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn-amd-amdhsa -target-cpu gfx906 -emit-llvm \ +// RUN: -verify -o - %s +// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn-amd-amdhsa -target-cpu gfx90a -emit-llvm \ +// RUN: -verify -o - %s +// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn-amd-amdhsa -target-cpu gfx940 -emit-llvm \ +// RUN: -verify -o - %s +// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -triple amdgcn-amd-amdhsa -target-cpu gfx1200 -emit-llvm \ +// RUN: -verify -o - %s + + +// REQUIRES: amdgpu-registered-target + +typedef unsigned int uint; +void test_prng_b32(global uint* out, uint a) { + *out = __builtin_amdgcn_prng_b32(a); // expected-error{{'__builtin_amdgcn_prng_b32' needs target feature prng-inst}} +} diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl new file mode 100644 index 0000000000000000000000000000000000000000..f31ba85a52a7adeca05272a2e28fbf768af2b9b9 --- /dev/null +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx950.cl @@ -0,0 +1,21 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -cl-std=CL1.2 -O0 -triple amdgcn-unknown-unknown -target-cpu gfx950 -emit-llvm -o - %s | FileCheck %s +// REQUIRES: amdgpu-registered-target + +typedef unsigned int uint; + +// CHECK-LABEL: @test_prng_b32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr addrspace(5) [[OUT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[A:%.*]], ptr addrspace(5) [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.amdgcn.prng.b32(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr addrspace(5) [[OUT_ADDR]], align 8 +// CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(1) [[TMP2]], align 4 +// CHECK-NEXT: ret void +// +void test_prng_b32(global uint* out, uint a) { + *out = __builtin_amdgcn_prng_b32(a); +} diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-mfma.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-mfma.cl index dcdeee6b6acc40e309c8b528aa0b7b70746c5220..841d8fcad0fee0ce8f8ce46a9c798f3b00cb7d42 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-mfma.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-mfma.cl @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx908 -DMFMA_GFX908_TESTS -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX908 // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx90a -DMFMA_GFX90A_TESTS -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX90A // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx940 -DMFMA_GFX940_TESTS -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX940 +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx950 -DMFMA_GFX950_TESTS -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX950 #pragma OPENCL EXTENSION cl_khr_fp64:enable @@ -23,6 +24,7 @@ typedef short v8s __attribute__((ext_vector_type(8))); typedef short v16s __attribute__((ext_vector_type(16))); typedef short v32s __attribute__((ext_vector_type(32))); typedef double v4d __attribute__((ext_vector_type(4))); +typedef __bf16 v8bf16 __attribute__((ext_vector_type(8))); #ifdef MFMA_GFX908_TESTS @@ -222,7 +224,7 @@ void test_mfma_f64_4x4x4f64(global double* out, double a, double b, double c) #endif // MFMA_GFX90A_TESTS -#ifdef MFMA_GFX940_TESTS +#if defined(MFMA_GFX940_TESTS) || defined(MFMA_GFX950_TESTS) // CHECK-GFX940-LABEL: @test_mfma_i32_16x16x32_i8 // CHECK-GFX940: call <4 x i32> @llvm.amdgcn.mfma.i32.16x16x32.i8(i64 %a, i64 %b, <4 x i32> %c, i32 0, i32 0, i32 0) void test_mfma_i32_16x16x32_i8(global v4i* out, long a, long b, v4i c) @@ -404,4 +406,29 @@ void test_smfmac_f32_32x32x32_fp8_fp8(global v16f* out, v2i a, v4i b, v16f c, in { *out = __builtin_amdgcn_smfmac_f32_32x32x32_fp8_fp8(a, b, c, idx, 0, 0); } -#endif // MFMA_GFX940_TESTS +#endif // defined(MFMA_GFX940_TESTS) || defined(MFMA_GFX950_TESTS) + +#ifdef MFMA_GFX950_TESTS + +// CHECK-GFX950-LABEL: @test_mfma_f32_16x16x32_f16( +// CHECK-GFX950: tail call <4 x float> @llvm.amdgcn.mfma.f32.16x16x32.f16(<8 x half> %a, <8 x half> %b, <4 x float> %c, i32 1, i32 2, i32 3) + +v4f test_mfma_f32_16x16x32_f16(v8h a, v8h b, v4f c) +{ + return __builtin_amdgcn_mfma_f32_16x16x32_f16(a, b, c, 1, 2, 3); +} + +// CHECK-GFX950-LABEL: @test_mfma_f32_32x32x16_f16 +// CHECK-GFX950: tail call <16 x float> @llvm.amdgcn.mfma.f32.32x32x16.f16(<8 x half> %a, <8 x half> %b, <16 x float> %c, i32 1, i32 2, i32 3) +v16f test_mfma_f32_32x32x16_f16(v8h a, v8h b, v16f c) +{ + return __builtin_amdgcn_mfma_f32_32x32x16_f16(a, b, c, 1, 2, 3); +} + +// CHECK-GFX950-LABEL: @test_mfma_f32_32x32x16_bf16( +// CHECK-GFX950: tail call <16 x float> @llvm.amdgcn.mfma.f32.32x32x16.bf16(<8 x bfloat> %a, <8 x bfloat> %b, <16 x float> %c, i32 1, i32 2, i32 3) +v16f test_mfma_f32_32x32x16_bf16(v8bf16 a, v8bf16 b, v16f c) { + return __builtin_amdgcn_mfma_f32_32x32x16_bf16(a, b, c, 1, 2, 3); +} + +#endif diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl b/clang/test/CodeGenOpenCL/builtins-f16.cl index 8150bc1ac9e2d7d351bf9d031d464a346252624e..e8b62fe0830cdbffe15a3a4d4dadf8c9bd0130a3 100644 --- a/clang/test/CodeGenOpenCL/builtins-f16.cl +++ b/clang/test/CodeGenOpenCL/builtins-f16.cl @@ -15,6 +15,9 @@ void test_half_builtins(half h0, half h1, half h2, int i0) { // CHECK: call half @llvm.atan.f16(half %h0) res = __builtin_atanf16(h0); + // CHECK: call half @llvm.atan2.f16(half %h0, half %h1) + res = __builtin_atan2f16(h0, h1); + // CHECK: call half @llvm.copysign.f16(half %h0, half %h1) res = __builtin_copysignf16(h0, h1); diff --git a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl index 1544770dfa4f3021b44c4016f6101ee4a656a13d..451d30b4d86f0ed3a9a45265189296323f14d7da 100644 --- a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl +++ b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl @@ -55,7 +55,7 @@ kernel void device_side_enqueue(global float *a, global float *b, int i) { // SPIR32-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[B_ADDR]], align 4 // SPIR32-NEXT: store ptr addrspace(1) [[TMP4]], ptr [[BLOCK_CAPTURED2]], align 4 // SPIR32-NEXT: [[TMP5:%.*]] = addrspacecast ptr [[BLOCK]] to ptr addrspace(4) -// SPIR32-NEXT: [[TMP6:%.*]] = call spir_func i32 @__enqueue_kernel_basic(target("spirv.Queue") [[TMP0]], i32 [[TMP1]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP]], ptr addrspace(4) addrspacecast (ptr @__device_side_enqueue_block_invoke_kernel to ptr addrspace(4)), ptr addrspace(4) [[TMP5]]) +// SPIR32-NEXT: [[TMP6:%.*]] = call spir_func i32 @__enqueue_kernel_basic(target("spirv.Queue") [[TMP0]], i32 [[TMP1]], ptr [[TMP]], ptr addrspace(4) addrspacecast (ptr @__device_side_enqueue_block_invoke_kernel to ptr addrspace(4)), ptr addrspace(4) [[TMP5]]) // SPIR32-NEXT: ret void // // @@ -126,7 +126,7 @@ kernel void device_side_enqueue(global float *a, global float *b, int i) { // STRICTFP-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[B_ADDR]], align 4 // STRICTFP-NEXT: store ptr addrspace(1) [[TMP4]], ptr [[BLOCK_CAPTURED2]], align 4 // STRICTFP-NEXT: [[TMP5:%.*]] = addrspacecast ptr [[BLOCK]] to ptr addrspace(4) -// STRICTFP-NEXT: [[TMP6:%.*]] = call spir_func i32 @__enqueue_kernel_basic(target("spirv.Queue") [[TMP0]], i32 [[TMP1]], ptr byval([[STRUCT_NDRANGE_T]]) [[TMP]], ptr addrspace(4) addrspacecast (ptr @__device_side_enqueue_block_invoke_kernel to ptr addrspace(4)), ptr addrspace(4) [[TMP5]]) +// STRICTFP-NEXT: [[TMP6:%.*]] = call spir_func i32 @__enqueue_kernel_basic(target("spirv.Queue") [[TMP0]], i32 [[TMP1]], ptr [[TMP]], ptr addrspace(4) addrspacecast (ptr @__device_side_enqueue_block_invoke_kernel to ptr addrspace(4)), ptr addrspace(4) [[TMP5]]) #[[ATTR5]] // STRICTFP-NEXT: ret void // // diff --git a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl index f0c164795b7642269caf24f5f5803da511307ce9..a1408d38a44c908daafe7177654e4dce5c0bf7e0 100644 --- a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl +++ b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue.cl @@ -89,8 +89,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) { // COMMON: store ptr addrspace(4) addrspacecast (ptr [[INVL1:@__device_side_enqueue_block_invoke[^ ]*]] to ptr addrspace(4)), ptr %block.invoke // COMMON: [[BL_I8:%[0-9]+]] ={{.*}} addrspacecast ptr %block to ptr addrspace(4) // COMMON-LABEL: call {{(spir_func )?}}i32 @__enqueue_kernel_basic( - // SPIR-SAME: target("spirv.Queue") [[DEF_Q]], i32 [[FLAGS]], ptr byval(%struct.ndrange_t) [[NDR]]{{([0-9]+)?}}, - // X86-SAME: ptr [[DEF_Q]], i32 [[FLAGS]], ptr byval(%struct.ndrange_t) [[NDR]]{{([0-9]+)?}}, + // SPIR-SAME: target("spirv.Queue") [[DEF_Q]], i32 [[FLAGS]], ptr [[NDR]]{{([0-9]+)?}}, + // X86-SAME: ptr [[DEF_Q]], i32 [[FLAGS]], ptr [[NDR]]{{([0-9]+)?}}, // COMMON-SAME: ptr addrspace(4) addrspacecast (ptr [[INVLK1:[^ ]+_kernel]] to ptr addrspace(4)), // COMMON-SAME: ptr addrspace(4) [[BL_I8]]) enqueue_kernel(default_queue, flags, ndrange, @@ -333,8 +333,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) { // X86: [[DEF_Q:%[0-9]+]] = load ptr, ptr %default_queue // COMMON: [[FLAGS:%[0-9]+]] = load i32, ptr %flags // COMMON-LABEL: call {{(spir_func )?}}i32 @__enqueue_kernel_basic( - // SPIR-SAME: target("spirv.Queue") [[DEF_Q]], i32 [[FLAGS]], ptr byval(%struct.ndrange_t) [[NDR]]{{([0-9]+)?}}, - // X86-SAME: ptr [[DEF_Q]], i32 [[FLAGS]], ptr byval(%struct.ndrange_t) [[NDR]]{{([0-9]+)?}}, + // SPIR-SAME: target("spirv.Queue") [[DEF_Q]], i32 [[FLAGS]], ptr [[NDR]]{{([0-9]+)?}}, + // X86-SAME: ptr [[DEF_Q]], i32 [[FLAGS]], ptr [[NDR]]{{([0-9]+)?}}, // COMMON-SAME: ptr addrspace(4) addrspacecast (ptr [[INVGK8:[^ ]+_kernel]] to ptr addrspace(4)), // COMMON-SAME: ptr addrspace(4) addrspacecast (ptr addrspace(1) [[BLG8]] to ptr addrspace(4))) enqueue_kernel(default_queue, flags, ndrange, block_A); @@ -382,8 +382,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i) { // COMMON: [[FLAGS:%[0-9]+]] = load i32, ptr %flags // COMMON: [[BL_I8:%[0-9]+]] ={{.*}} addrspacecast ptr {{.*}} to ptr addrspace(4) // COMMON-LABEL: call {{(spir_func )?}}i32 @__enqueue_kernel_basic( - // SPIR-SAME: target("spirv.Queue") [[DEF_Q]], i32 [[FLAGS]], ptr byval(%struct.ndrange_t) [[NDR]]{{([0-9]+)?}}, - // X86-SAME: ptr [[DEF_Q]], i32 [[FLAGS]], ptr byval(%struct.ndrange_t) [[NDR]]{{([0-9]+)?}}, + // SPIR-SAME: target("spirv.Queue") [[DEF_Q]], i32 [[FLAGS]], ptr [[NDR]]{{([0-9]+)?}}, + // X86-SAME: ptr [[DEF_Q]], i32 [[FLAGS]], ptr [[NDR]]{{([0-9]+)?}}, // COMMON-SAME: ptr addrspace(4) addrspacecast (ptr [[INVLK3:[^ ]+_kernel]] to ptr addrspace(4)), // COMMON-SAME: ptr addrspace(4) [[BL_I8]]) enqueue_kernel(default_queue, flags, ndrange, block_C); diff --git a/clang/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl b/clang/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl index f39589ada0a70346220ed644223d920d9b253f9b..2aeeb637795a9df44f425f399a1da65082b078cc 100644 --- a/clang/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl +++ b/clang/test/CodeGenOpenCL/kernels-have-spir-cc-by-default.cl @@ -28,7 +28,7 @@ kernel void test_single(int_single input, global int* output) { // CHECK: spir_kernel // AMDGCN: define{{.*}} amdgpu_kernel void @test_single // CHECK: ptr nocapture {{.*}} byval(%struct.int_single) -// CHECK: ptr nocapture noundef writeonly align 4 %output +// CHECK: ptr nocapture noundef writeonly align 4 initializes((0, 4)) %output output[0] = input.a; } @@ -36,7 +36,7 @@ kernel void test_pair(int_pair input, global int* output) { // CHECK: spir_kernel // AMDGCN: define{{.*}} amdgpu_kernel void @test_pair // CHECK: ptr nocapture {{.*}} byval(%struct.int_pair) -// CHECK: ptr nocapture noundef writeonly align 4 %output +// CHECK: ptr nocapture noundef writeonly align 4 initializes((0, 8)) %output output[0] = (int)input.a; output[1] = (int)input.b; } @@ -45,7 +45,7 @@ kernel void test_kernel(test_struct input, global int* output) { // CHECK: spir_kernel // AMDGCN: define{{.*}} amdgpu_kernel void @test_kernel // CHECK: ptr nocapture {{.*}} byval(%struct.test_struct) -// CHECK: ptr nocapture noundef writeonly align 4 %output +// CHECK: ptr nocapture noundef writeonly align 4 initializes((0, 32)) %output output[0] = input.elementA; output[1] = input.elementB; output[2] = (int)input.elementC; @@ -59,7 +59,7 @@ kernel void test_kernel(test_struct input, global int* output) { void test_function(int_pair input, global int* output) { // CHECK-NOT: spir_kernel // AMDGCN-NOT: define{{.*}} amdgpu_kernel void @test_function -// CHECK: i64 %input.coerce0, i64 %input.coerce1, ptr nocapture noundef writeonly %output +// CHECK: i64 %input.coerce0, i64 %input.coerce1, ptr nocapture noundef writeonly initializes((0, 8)) %output output[0] = (int)input.a; output[1] = (int)input.b; } diff --git a/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp index db9d7eb3281fce2fceefd3649922e7dfd270b0bb..86f21ee556ce83044222b47ad42aef1c02491592 100644 --- a/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp +++ b/clang/test/CodeGenOpenCLCXX/array-type-infinite-loop.clcpp @@ -2,7 +2,7 @@ //RUN: %clang_cc1 %s -triple spir -emit-llvm -O1 -o - | FileCheck %s // CHECK-LABEL: define dso_local spir_kernel void @test( -// CHECK-SAME: ptr addrspace(1) nocapture noundef readonly align 8 [[IN:%.*]], ptr addrspace(1) nocapture noundef writeonly align 8 [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META3:![0-9]+]] !kernel_arg_access_qual [[META4:![0-9]+]] !kernel_arg_type [[META5:![0-9]+]] !kernel_arg_base_type [[META5]] !kernel_arg_type_qual [[META6:![0-9]+]] { +// CHECK-SAME: ptr addrspace(1) nocapture noundef readonly align 8 [[IN:%.*]], ptr addrspace(1) nocapture noundef writeonly align 8 initializes((0, 8)) [[OUT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] !kernel_arg_addr_space [[META3:![0-9]+]] !kernel_arg_access_qual [[META4:![0-9]+]] !kernel_arg_type [[META5:![0-9]+]] !kernel_arg_base_type [[META5]] !kernel_arg_type_qual [[META6:![0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[IN]], i32 8 // CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(1) [[ARRAYIDX1]], align 8, !tbaa [[TBAA7:![0-9]+]] diff --git a/clang/test/Driver/Inputs/cpunative/cortex-a57 b/clang/test/Driver/Inputs/cpunative/cortex-a57 new file mode 100644 index 0000000000000000000000000000000000000000..e1903012ab79ccda38c861ce11b9f32c1a8892aa --- /dev/null +++ b/clang/test/Driver/Inputs/cpunative/cortex-a57 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 200.00 +Features : fp asimd evtstrm crc32 cpuid +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x1 +CPU part : 0xd07 +CPU revision : 1 diff --git a/clang/test/Driver/Inputs/cpunative/cortex-a72 b/clang/test/Driver/Inputs/cpunative/cortex-a72 new file mode 100644 index 0000000000000000000000000000000000000000..7aed4a6fa732369477adbbbb0f0c1271df6651ba --- /dev/null +++ b/clang/test/Driver/Inputs/cpunative/cortex-a72 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 250.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid asimdrdm +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x0 +CPU part : 0xd08 +CPU revision : 2 diff --git a/clang/test/Driver/Inputs/cpunative/cortex-a76 b/clang/test/Driver/Inputs/cpunative/cortex-a76 new file mode 100644 index 0000000000000000000000000000000000000000..21822cfcec60b0e6e7316f69875c9d6d88d28242 --- /dev/null +++ b/clang/test/Driver/Inputs/cpunative/cortex-a76 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 500.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics cpuid asimdrdm ssbs jscvt fcma +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x1 +CPU part : 0xd0b +CPU revision : 2 diff --git a/clang/test/Driver/Inputs/cpunative/neoverse-n1 b/clang/test/Driver/Inputs/cpunative/neoverse-n1 new file mode 100644 index 0000000000000000000000000000000000000000..571e8840b09f08a82665ab1e1997fc7afde117cf --- /dev/null +++ b/clang/test/Driver/Inputs/cpunative/neoverse-n1 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 50.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x3 +CPU part : 0xd0c +CPU revision : 1 diff --git a/clang/test/Driver/Inputs/cpunative/neoverse-v2 b/clang/test/Driver/Inputs/cpunative/neoverse-v2 new file mode 100644 index 0000000000000000000000000000000000000000..c3c8433415d7a08c60057c01a91bafceba4923e7 --- /dev/null +++ b/clang/test/Driver/Inputs/cpunative/neoverse-v2 @@ -0,0 +1,8 @@ +processor : 0 +BogoMIPS : 2000.00 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm ssbs sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh bti +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant : 0x0 +CPU part : 0xd4f +CPU revision : 0 diff --git a/clang/test/Driver/aarch64-implied-sme-features.c b/clang/test/Driver/aarch64-implied-sme-features.c index eca62e2563b78835a398407c6f4d055aa64ccfca..4d507c0e99dd919d26d080dd56d5f857c451e6bd 100644 --- a/clang/test/Driver/aarch64-implied-sme-features.c +++ b/clang/test/Driver/aarch64-implied-sme-features.c @@ -49,3 +49,6 @@ // RUN: %clang -target aarch64-linux-gnu -march=armv8-a+nosme+sme-i16i64 %s -### 2>&1 | FileCheck %s --check-prefix=SME-SUBFEATURE-CONFLICT-REV // SME-SUBFEATURE-CONFLICT-REV: "-target-feature" "+bf16"{{.*}} "-target-feature" "+sme" "-target-feature" "+sme-i16i64" + +// RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+ssve-aes %s -### 2>&1 | FileCheck %s --check-prefix=SVE-AES +// SVE-AES: "-target-feature" "+sme" "-target-feature" "+sme2" "-target-feature" "+ssve-aes" "-target-feature" "+sve-aes" \ No newline at end of file diff --git a/clang/test/Driver/aarch64-implied-sve-features.c b/clang/test/Driver/aarch64-implied-sve-features.c index f04e1a785673b87649d5ac19cf82beaf3ca05905..e5f1e553454143c6fe779d612e0c23adaf771603 100644 --- a/clang/test/Driver/aarch64-implied-sve-features.c +++ b/clang/test/Driver/aarch64-implied-sve-features.c @@ -36,7 +36,7 @@ // SVE2-BITPERM-REVERT: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "-sve2-bitperm" // RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+sve2-aes+nosve2-aes %s -### 2>&1 | FileCheck %s --check-prefix=SVE2-AES-REVERT -// SVE2-AES-REVERT: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "-sve2-aes" +// SVE2-AES-REVERT: "-target-feature" "+sve" "-target-feature" "-sve-aes" "-target-feature" "+sve2" "-target-feature" "-sve2-aes" // RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+sve2-sha3+nosve2-sha3 %s -### 2>&1 | FileCheck %s --check-prefix=SVE2-SHA3-REVERT // SVE2-SHA3-REVERT: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "-sve2-sha3" @@ -47,8 +47,11 @@ // RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+sve2-sha3 %s -### 2>&1 | FileCheck %s --check-prefix=SVE2-SHA3 // SVE2-SHA3: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "+sve2-sha3" +// RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+sve-aes %s -### 2>&1 | FileCheck %s --check-prefix=SVE-AES +// SVE-AES: "-target-feature" "+aes"{{.*}} "-target-feature" "+sve-aes" + // RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+sve2-aes %s -### 2>&1 | FileCheck %s --check-prefix=SVE2-AES -// SVE2-AES: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "+sve2-aes" +// SVE2-AES: "-target-feature" "+sve" "-target-feature" "+sve-aes" "-target-feature" "+sve2" "-target-feature" "+sve2-aes" // RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+sve2-sm4 %s -### 2>&1 | FileCheck %s --check-prefix=SVE2-SM4 // SVE2-SM4: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "+sve2-sm4" @@ -66,7 +69,7 @@ // SVE-SUBFEATURE-CONFLICT-NOT: "-target-feature" "+sve" // RUN: %clang --target=aarch64-linux-gnu -march=armv8-a+nosve+sve2-aes %s -### 2>&1 | FileCheck %s --check-prefix=SVE-SUBFEATURE-CONFLICT-REV -// SVE-SUBFEATURE-CONFLICT-REV: "-target-feature" "+sve" "-target-feature" "+sve2" "-target-feature" "+sve2-aes" +// SVE-SUBFEATURE-CONFLICT-REV: "-target-feature" "+sve" "-target-feature" "+sve-aes" "-target-feature" "+sve2" "-target-feature" "+sve2-aes" // RUN: %clang --target=aarch64-linux-gnu -mcpu=neoverse-n2+nosve2 %s -### 2>&1 | FileCheck %s --check-prefix=SVE-MCPU-FEATURES // SVE-MCPU-FEATURES-NOT: "-target-feature" "+sve2-bitperm" diff --git a/clang/test/Driver/aarch64-mcpu-native.c b/clang/test/Driver/aarch64-mcpu-native.c new file mode 100644 index 0000000000000000000000000000000000000000..2e7fc2c5adc4532dde659f1cd9eb9dae915be839 --- /dev/null +++ b/clang/test/Driver/aarch64-mcpu-native.c @@ -0,0 +1,138 @@ +// REQUIRES: aarch64-registered-target,system-linux,aarch64-host +// RUN: export LLVM_CPUINFO=%S/Inputs/cpunative/neoverse-v2 +// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --check-prefix=CHECK-FEAT-NV2 --implicit-check-not=FEAT_ %s + +// CHECK-FEAT-NV2: Extensions enabled for the given AArch64 target +// CHECK-FEAT-NV2-EMPTY: +// CHECK-FEAT-NV2: Architecture Feature(s) Description +// CHECK-FEAT-NV2: FEAT_AES, FEAT_PMULL Enable AES support +// CHECK-FEAT-NV2: FEAT_AMUv1 Enable Armv8.4-A Activity Monitors extension +// CHECK-FEAT-NV2: FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-FEAT-NV2: FEAT_BF16 Enable BFloat16 Extension +// CHECK-FEAT-NV2: FEAT_BTI Enable Branch Target Identification +// CHECK-FEAT-NV2: FEAT_CCIDX Enable Armv8.3-A Extend of the CCSIDR number of sets +// CHECK-FEAT-NV2: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions +// CHECK-FEAT-NV2: FEAT_CSV2_2 Enable architectural speculation restriction +// CHECK-FEAT-NV2: FEAT_DIT Enable Armv8.4-A Data Independent Timing instructions +// CHECK-FEAT-NV2: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence +// CHECK-FEAT-NV2: FEAT_DPB2 Enable Armv8.5-A Cache Clean to Point of Deep Persistence +// CHECK-FEAT-NV2: FEAT_DotProd Enable dot product support +// CHECK-FEAT-NV2: FEAT_ETE Enable Embedded Trace Extension +// CHECK-FEAT-NV2: FEAT_FCMA Enable Armv8.3-A Floating-point complex number support +// CHECK-FEAT-NV2: FEAT_FHM Enable FP16 FML instructions +// CHECK-FEAT-NV2: FEAT_FP Enable Armv8.0-A Floating Point Extensions +// CHECK-FEAT-NV2: FEAT_FP16 Enable half-precision floating-point data processing +// CHECK-FEAT-NV2: FEAT_FRINTTS Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int +// CHECK-FEAT-NV2: FEAT_FlagM Enable Armv8.4-A Flag Manipulation instructions +// CHECK-FEAT-NV2: FEAT_FlagM2 Enable alternative NZCV format for floating point comparisons +// CHECK-FEAT-NV2: FEAT_I8MM Enable Matrix Multiply Int8 Extension +// CHECK-FEAT-NV2: FEAT_JSCVT Enable Armv8.3-A JavaScript FP conversion instructions +// CHECK-FEAT-NV2: FEAT_LOR Enable Armv8.1-A Limited Ordering Regions extension +// CHECK-FEAT-NV2: FEAT_LRCPC Enable support for RCPC extension +// CHECK-FEAT-NV2: FEAT_LRCPC2 Enable Armv8.4-A RCPC instructions with Immediate Offsets +// CHECK-FEAT-NV2: FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions +// CHECK-FEAT-NV2: FEAT_LSE2 Enable Armv8.4-A Large System Extension 2 (LSE2) atomicity rules +// CHECK-FEAT-NV2: FEAT_MPAM Enable Armv8.4-A Memory system Partitioning and Monitoring extension +// CHECK-FEAT-NV2: FEAT_MTE, FEAT_MTE2 Enable Memory Tagging Extension +// CHECK-FEAT-NV2: FEAT_NV, FEAT_NV2 Enable Armv8.4-A Nested Virtualization Enchancement +// CHECK-FEAT-NV2: FEAT_PAN Enable Armv8.1-A Privileged Access-Never extension +// CHECK-FEAT-NV2: FEAT_PAN2 Enable Armv8.2-A PAN s1e1R and s1e1W Variants +// CHECK-FEAT-NV2: FEAT_PAuth Enable Armv8.3-A Pointer Authentication extension +// CHECK-FEAT-NV2: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension +// CHECK-FEAT-NV2: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions +// CHECK-FEAT-NV2: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions +// CHECK-FEAT-NV2: FEAT_RNG Enable Random Number generation instructions +// CHECK-FEAT-NV2: FEAT_SB Enable Armv8.5-A Speculation Barrier +// CHECK-FEAT-NV2: FEAT_SEL2 Enable Armv8.4-A Secure Exception Level 2 extension +// CHECK-FEAT-NV2: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support +// CHECK-FEAT-NV2: FEAT_SPE Enable Statistical Profiling extension +// CHECK-FEAT-NV2: FEAT_SPECRES Enable Armv8.5-A execution and data prediction invalidation instructions +// CHECK-FEAT-NV2: FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit +// CHECK-FEAT-NV2: FEAT_SVE Enable Scalable Vector Extension (SVE) instructions +// CHECK-FEAT-NV2: FEAT_SVE2 Enable Scalable Vector Extension 2 (SVE2) instructions +// CHECK-FEAT-NV2: FEAT_SVE_BitPerm Enable bit permutation SVE2 instructions +// CHECK-FEAT-NV2: FEAT_TLBIOS, FEAT_TLBIRANGE Enable Armv8.4-A TLB Range and Maintenance instructions +// CHECK-FEAT-NV2: FEAT_TRBE Enable Trace Buffer Extension +// CHECK-FEAT-NV2: FEAT_TRF Enable Armv8.4-A Trace extension +// CHECK-FEAT-NV2: FEAT_UAO Enable Armv8.2-A UAO PState +// CHECK-FEAT-NV2: FEAT_VHE Enable Armv8.1-A Virtual Host extension + +// RUN: export LLVM_CPUINFO=%S/Inputs/cpunative/neoverse-n1 +// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --check-prefix=CHECK-FEAT-NN1 --implicit-check-not=FEAT_ %s + +// CHECK-FEAT-NN1: Extensions enabled for the given AArch64 target +// CHECK-FEAT-NN1-EMPTY: +// CHECK-FEAT-NN1: Architecture Feature(s) Description +// CHECK-FEAT-NN1: FEAT_AES, FEAT_PMULL Enable AES support +// CHECK-FEAT-NN1: FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-FEAT-NN1: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions +// CHECK-FEAT-NN1: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence +// CHECK-FEAT-NN1: FEAT_DotProd Enable dot product support +// CHECK-FEAT-NN1: FEAT_FP Enable Armv8.0-A Floating Point Extensions +// CHECK-FEAT-NN1: FEAT_FP16 Enable half-precision floating-point data processing +// CHECK-FEAT-NN1: FEAT_LOR Enable Armv8.1-A Limited Ordering Regions extension +// CHECK-FEAT-NN1: FEAT_LRCPC Enable support for RCPC extension +// CHECK-FEAT-NN1: FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions +// CHECK-FEAT-NN1: FEAT_PAN Enable Armv8.1-A Privileged Access-Never extension +// CHECK-FEAT-NN1: FEAT_PAN2 Enable Armv8.2-A PAN s1e1R and s1e1W Variants +// CHECK-FEAT-NN1: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension +// CHECK-FEAT-NN1: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions +// CHECK-FEAT-NN1: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions +// CHECK-FEAT-NN1: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support +// CHECK-FEAT-NN1: FEAT_SPE Enable Statistical Profiling extension +// CHECK-FEAT-NN1: FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit +// CHECK-FEAT-NN1: FEAT_UAO Enable Armv8.2-A UAO PState +// CHECK-FEAT-NN1: FEAT_VHE Enable Armv8.1-A Virtual Host extension + + +// RUN: export LLVM_CPUINFO=%S/Inputs/cpunative/cortex-a57 +// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --check-prefix=CHECK-FEAT-CA57 --implicit-check-not=FEAT_ %s + +// CHECK-FEAT-CA57: Extensions enabled for the given AArch64 target +// CHECK-FEAT-CA57-EMPTY: +// CHECK-FEAT-CA57: Architecture Feature(s) Description +// CHECK-FEAT-CA57: FEAT_AES, FEAT_PMULL Enable AES support +// CHECK-FEAT-CA57: FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-FEAT-CA57: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions +// CHECK-FEAT-CA57: FEAT_FP Enable Armv8.0-A Floating Point Extensions +// CHECK-FEAT-CA57: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension +// CHECK-FEAT-CA57: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support + +// RUN: export LLVM_CPUINFO=%S/Inputs/cpunative/cortex-a72 +// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --check-prefix=CHECK-FEAT-CA72 --implicit-check-not=FEAT_ %s + +// CHECK-FEAT-CA72: Extensions enabled for the given AArch64 target +// CHECK-EMPTY: +// CHECK-FEAT-CA72: Architecture Feature(s) Description +// CHECK-FEAT-CA72: FEAT_AES, FEAT_PMULL Enable AES support +// CHECK-FEAT-CA72: FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-FEAT-CA72: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions +// CHECK-FEAT-CA72: FEAT_FP Enable Armv8.0-A Floating Point Extensions +// CHECK-FEAT-CA72: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension +// CHECK-FEAT-CA72: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support + +// RUN: export LLVM_CPUINFO=%S/Inputs/cpunative/cortex-a76 +// RUN: %clang --target=aarch64 --print-enabled-extensions -mcpu=native | FileCheck --strict-whitespace --check-prefix=CHECK-FEAT-CA76 --implicit-check-not=FEAT_ %s + +// CHECK-FEAT-CA76: Extensions enabled for the given AArch64 target +// CHECK-FEAT-CA76-EMPTY: +// CHECK-FEAT-CA76: Architecture Feature(s) Description +// CHECK-FEAT-CA76: FEAT_AES, FEAT_PMULL Enable AES support +// CHECK-FEAT-CA76: FEAT_AdvSIMD Enable Advanced SIMD instructions +// CHECK-FEAT-CA76: FEAT_CRC32 Enable Armv8.0-A CRC-32 checksum instructions +// CHECK-FEAT-CA76: FEAT_DPB Enable Armv8.2-A data Cache Clean to Point of Persistence +// CHECK-FEAT-CA76: FEAT_DotProd Enable dot product support +// CHECK-FEAT-CA76: FEAT_FP Enable Armv8.0-A Floating Point Extensions +// CHECK-FEAT-CA76: FEAT_FP16 Enable half-precision floating-point data processing +// CHECK-FEAT-CA76: FEAT_LOR Enable Armv8.1-A Limited Ordering Regions extension +// CHECK-FEAT-CA76: FEAT_LRCPC Enable support for RCPC extension +// CHECK-FEAT-CA76: FEAT_LSE Enable Armv8.1-A Large System Extension (LSE) atomic instructions +// CHECK-FEAT-CA76: FEAT_PAN Enable Armv8.1-A Privileged Access-Never extension +// CHECK-FEAT-CA76: FEAT_PAN2 Enable Armv8.2-A PAN s1e1R and s1e1W Variants +// CHECK-FEAT-CA76: FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension +// CHECK-FEAT-CA76: FEAT_RAS, FEAT_RASv1p1 Enable Armv8.0-A Reliability, Availability and Serviceability Extensions +// CHECK-FEAT-CA76: FEAT_RDM Enable Armv8.1-A Rounding Double Multiply Add/Subtract instructions +// CHECK-FEAT-CA76: FEAT_SHA1, FEAT_SHA256 Enable SHA1 and SHA256 support +// CHECK-FEAT-CA76: FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit +// CHECK-FEAT-CA76: FEAT_UAO Enable Armv8.2-A UAO PState +// CHECK-FEAT-CA76: FEAT_VHE Enable Armv8.1-A Virtual Host extension diff --git a/clang/test/Driver/amdgpu-hip-system-arch.c b/clang/test/Driver/amdgpu-hip-system-arch.c index f25a4087080f6db07fd9817b6509e61a87ee1811..9c27bc09fb36cfc2b6df5aed93e4b4e783a17737 100644 --- a/clang/test/Driver/amdgpu-hip-system-arch.c +++ b/clang/test/Driver/amdgpu-hip-system-arch.c @@ -1,5 +1,5 @@ -// REQUIRES: system-linux // REQUIRES: shell +// XFAIL: target={{.*}}-zos{{.*}} // RUN: mkdir -p %t // RUN: cp %S/Inputs/amdgpu-arch/amdgpu_arch_fail %t/ diff --git a/clang/test/Driver/amdgpu-macros.cl b/clang/test/Driver/amdgpu-macros.cl index 2fedd10bb534458c5252cbd873d3b24b629f5a9d..d97b2ddb1fc663528a3bb9ccabaee3d3b61e16c2 100644 --- a/clang/test/Driver/amdgpu-macros.cl +++ b/clang/test/Driver/amdgpu-macros.cl @@ -110,6 +110,7 @@ // RUN: %clang -E -dM -target amdgcn -mcpu=gfx940 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx940 -DFAMILY=GFX9 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx941 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx941 -DFAMILY=GFX9 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx942 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx942 -DFAMILY=GFX9 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx950 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx950 -DFAMILY=GFX9 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1010 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1010 -DFAMILY=GFX10 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1011 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1011 -DFAMILY=GFX10 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1012 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1012 -DFAMILY=GFX10 @@ -133,6 +134,7 @@ // RUN: %clang -E -dM -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1201 -DFAMILY=GFX12 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx9-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx9_generic -DFAMILY=GFX9 +// RUN: %clang -E -dM -target amdgcn -mcpu=gfx9-4-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=64 -DCPU=gfx9_4_generic -DFAMILY=GFX9 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx10-1-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx10_1_generic -DFAMILY=GFX10 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx10-3-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx10_3_generic -DFAMILY=GFX10 // RUN: %clang -E -dM -target amdgcn -mcpu=gfx11-generic %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx11_generic -DFAMILY=GFX11 diff --git a/clang/test/Driver/amdgpu-mcpu.cl b/clang/test/Driver/amdgpu-mcpu.cl index 42ce33db6eec07999028e2e9079384e48590adca..7c34d3ec6c63a9d62f2277bc2e2c794bde7523f7 100644 --- a/clang/test/Driver/amdgpu-mcpu.cl +++ b/clang/test/Driver/amdgpu-mcpu.cl @@ -95,6 +95,7 @@ // RUN: %clang -### -target amdgcn -mcpu=gfx940 %s 2>&1 | FileCheck --check-prefix=GFX940 %s // RUN: %clang -### -target amdgcn -mcpu=gfx941 %s 2>&1 | FileCheck --check-prefix=GFX941 %s // RUN: %clang -### -target amdgcn -mcpu=gfx942 %s 2>&1 | FileCheck --check-prefix=GFX942 %s +// RUN: %clang -### -target amdgcn -mcpu=gfx950 %s 2>&1 | FileCheck --check-prefix=GFX950 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1010 %s 2>&1 | FileCheck --check-prefix=GFX1010 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1011 %s 2>&1 | FileCheck --check-prefix=GFX1011 %s // RUN: %clang -### -target amdgcn -mcpu=gfx1012 %s 2>&1 | FileCheck --check-prefix=GFX1012 %s @@ -118,6 +119,7 @@ // RUN: %clang -### -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefix=GFX1201 %s // RUN: %clang -### -target amdgcn -mcpu=gfx9-generic %s 2>&1 | FileCheck --check-prefix=GFX9_GENERIC %s +// RUN: %clang -### -target amdgcn -mcpu=gfx9-4-generic %s 2>&1 | FileCheck --check-prefix=GFX9_4_GENERIC %s // RUN: %clang -### -target amdgcn -mcpu=gfx10-1-generic %s 2>&1 | FileCheck --check-prefix=GFX10_1_GENERIC %s // RUN: %clang -### -target amdgcn -mcpu=gfx10-3-generic %s 2>&1 | FileCheck --check-prefix=GFX10_3_GENERIC %s // RUN: %clang -### -target amdgcn -mcpu=gfx11-generic %s 2>&1 | FileCheck --check-prefix=GFX11_GENERIC %s @@ -149,6 +151,7 @@ // GFX940: "-target-cpu" "gfx940" // GFX941: "-target-cpu" "gfx941" // GFX942: "-target-cpu" "gfx942" +// GFX950: "-target-cpu" "gfx950" // GFX1010: "-target-cpu" "gfx1010" // GFX1011: "-target-cpu" "gfx1011" // GFX1012: "-target-cpu" "gfx1012" @@ -172,6 +175,7 @@ // GFX1201: "-target-cpu" "gfx1201" // GFX9_GENERIC: "-target-cpu" "gfx9-generic" +// GFX9_4_GENERIC: "-target-cpu" "gfx9-4-generic" // GFX10_1_GENERIC: "-target-cpu" "gfx10-1-generic" // GFX10_3_GENERIC: "-target-cpu" "gfx10-3-generic" // GFX11_GENERIC: "-target-cpu" "gfx11-generic" diff --git a/clang/test/Driver/amdgpu-openmp-system-arch-fail.c b/clang/test/Driver/amdgpu-openmp-system-arch-fail.c index 85c82e4598cb10ab6f225a50ce0e70cd3f1f8b83..b7e1d0b2c566592570f13d034868d654306d31a0 100644 --- a/clang/test/Driver/amdgpu-openmp-system-arch-fail.c +++ b/clang/test/Driver/amdgpu-openmp-system-arch-fail.c @@ -1,4 +1,3 @@ -// REQUIRES: system-linux // REQUIRES: shell // RUN: mkdir -p %t diff --git a/clang/test/Driver/arm-alignment.c b/clang/test/Driver/arm-alignment.c index 8c915477af9affddda338bae7011b27cef8c96f1..b714f80a07dc12aac761c94fdf67520f1f3ea155 100644 --- a/clang/test/Driver/arm-alignment.c +++ b/clang/test/Driver/arm-alignment.c @@ -37,6 +37,12 @@ // RUN: %clang -target thumbv8m.base-none-gnueabi -### %s 2> %t // RUN: FileCheck --check-prefix CHECK-ALIGNED-ARM <%t %s +// RUN: %clang -target armv7em-apple-unknown-macho -mthumb -### %s 2> %t +// RUN: FileCheck --check-prefix CHECK-ALIGNED-ARM <%t %s + +// RUN: %clang -target armv7em-apple-darwin -mthumb -### %s 2> %t +// RUN: FileCheck --check-prefix CHECK-ALIGNED-ARM <%t %s + // RUN: %clang --target=aarch64 -munaligned-access -### %s 2> %t // RUN: FileCheck --check-prefix=CHECK-UNALIGNED-AARCH64 < %t %s diff --git a/clang/test/Driver/cl-zc.cpp b/clang/test/Driver/cl-zc.cpp index 9b1ea53888ceb5ab44b7a1324ae0e091c09834e2..5f0cd5e00819dd417f5dbd00a2f7f965f6f163b3 100644 --- a/clang/test/Driver/cl-zc.cpp +++ b/clang/test/Driver/cl-zc.cpp @@ -99,6 +99,9 @@ // RUN: %clang_cl /Zc:threadSafeInit /c -### -- %s 2>&1 | FileCheck -check-prefix=ThreadSafeStatics %s // ThreadSafeStatics-NOT: "-fno-threadsafe-statics" +// RUN: %clang_cl /Zc:tlsGuards- /c -### -- %s 2>&1 | FileCheck -check-prefix=NoTlsGuards %s +// NoTlsGuards: "-fno-ms-tls-guards" + // RUN: %clang_cl /Zc:dllexportInlines- /c -### -- %s 2>&1 | FileCheck -check-prefix=NoDllExportInlines %s // NoDllExportInlines: "-fno-dllexport-inlines" // RUN: %clang_cl /Zc:dllexportInlines /c -### -- %s 2>&1 | FileCheck -check-prefix=DllExportInlines %s diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index 2cfbe256bc745629336dc194aca7c999878011d6..ddbf1fd951c84e12399e6cd944a3ff747a0b2c8b 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -71,9 +71,6 @@ // RUN: %clang -### -S -fauto-profile=%S/Inputs/file.prof -fno-auto-profile %s 2>&1 | FileCheck -check-prefix=CHECK-NO-AUTO-PROFILE %s // CHECK-NO-AUTO-PROFILE-NOT: "-fprofile-sample-use={{.*}}/file.prof" -// RUN: %clang -### -S -fauto-profile=%S/Inputs/file.prof -fno-profile-sample-use -fauto-profile %s 2>&1 | FileCheck -check-prefix=CHECK-AUTO-PROFILE %s -// RUN: %clang -### -S -fauto-profile=%S/Inputs/file.prof -fno-auto-profile -fprofile-sample-use %s 2>&1 | FileCheck -check-prefix=CHECK-AUTO-PROFILE %s - // RUN: %clang -### -S -fprofile-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-LLVM %s // RUN: %clang -### -S -fprofile-instr-generate %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE %s // RUN: %clang -### -S -fprofile-generate=/some/dir %s 2>&1 | FileCheck -check-prefix=CHECK-PROFILE-GENERATE-DIR %s diff --git a/clang/test/Driver/darwin-subframeworks.c b/clang/test/Driver/darwin-subframeworks.c new file mode 100644 index 0000000000000000000000000000000000000000..1a7a095c6429227382183f9049ba44aa52a5ed1e --- /dev/null +++ b/clang/test/Driver/darwin-subframeworks.c @@ -0,0 +1,18 @@ +// UNSUPPORTED: system-windows +// Windows is unsupported because we use the Unix path separator `\`. + +// Add default directories before running clang to check default +// search paths. +// RUN: rm -rf %t && mkdir -p %t +// RUN: cp -R %S/Inputs/MacOSX15.1.sdk %t/ +// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/Frameworks +// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/SubFrameworks +// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include + +// RUN: %clang %s -target arm64-apple-darwin13.0 -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck %s + +// CHECK: -isysroot [[PATH:[^ ]*/MacOSX15.1.sdk]] +// CHECK: #include <...> search starts here: +// CHECK: [[PATH]]/usr/include +// CHECK: [[PATH]]/System/Library/Frameworks (framework directory) +// CHECK: [[PATH]]/System/Library/SubFrameworks (framework directory) diff --git a/clang/test/Driver/fprofile-sample-use.c b/clang/test/Driver/fprofile-sample-use.c new file mode 100644 index 0000000000000000000000000000000000000000..7c8813a83785ceb15a44d100efa47943a9bb1548 --- /dev/null +++ b/clang/test/Driver/fprofile-sample-use.c @@ -0,0 +1,5 @@ +/// GCC -fauto-profile (without =) is rejected. +/// -fprofile-sample-use without = is rejected as well. +// RUN: not %clang -### -S -fauto-profile -fprofile-sample-use %s 2>&1 | FileCheck %s --check-prefix=ERR +// ERR: error: unknown argument: '-fauto-profile' +// ERR: error: unknown argument: '-fprofile-sample-use' diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 6ecf0b57bee5c0d2ddb4cc1a4bb3002a25a95624..15f190165a7d73fd2056cbe61bb28f619c4f72f4 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -866,6 +866,13 @@ // CHECK-INTSAN-MINIMAL: "-fsanitize=integer-divide-by-zero,shift-base,shift-exponent,signed-integer-overflow,unsigned-integer-overflow,unsigned-shift-base,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change" // CHECK-INTSAN-MINIMAL: "-fsanitize-minimal-runtime" +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=implicit-conversion -fsanitize-trap=implicit-conversion %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-IMPL-CONV-TRAP +// CHECK-IMPL-CONV-TRAP: "-fsanitize-trap=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,implicit-bitfield-conversion" + +// RUN: %clang --target=x86_64-linux-gnu -fsanitize=implicit-conversion -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-IMPL-CONV-MINIMAL +// CHECK-IMPL-CONV-MINIMAL: "-fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,implicit-bitfield-conversion" +// CHECK-IMPL-CONV-MINIMAL: "-fsanitize-minimal-runtime" + // RUN: %clang --target=aarch64-linux-android -march=armv8-a+memtag -fsanitize=memtag -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-MEMTAG-MINIMAL // CHECK-MEMTAG-MINIMAL: "-fsanitize=memtag-stack,memtag-heap,memtag-globals" // CHECK-MEMTAG-MINIMAL: "-fsanitize-minimal-runtime" diff --git a/clang/test/Driver/hip-device-libs.hip b/clang/test/Driver/hip-device-libs.hip index 97f9f9290f40029863c31e78220e90a318bc91e2..6f1d31508e330213881d272a667a08293eda1a99 100644 --- a/clang/test/Driver/hip-device-libs.hip +++ b/clang/test/Driver/hip-device-libs.hip @@ -157,11 +157,12 @@ // Test default code object version. // RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=gfx900 \ // RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ -// RUN: 2>&1 | FileCheck %s --check-prefixes=ABI4 +// RUN: 2>&1 | FileCheck %s --check-prefixes=ABI5 // Test default code object version with old device library without abi_version_400.bc // RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=gfx900 \ -// RUN: --hip-device-lib-path=%S/Inputs/rocm/amdgcn/bitcode-no-abi-ver \ +// RUN: -mcode-object-version=4 \ +// RUN: --hip-device-lib-path=%S/Inputs/rocm/amdgcn/bitcode-no-abi-ver \ // RUN: --rocm-path=%S/Inputs/rocm %S/Inputs/hip_multiple_inputs/b.hip \ // RUN: 2>&1 | FileCheck %s --check-prefixes=NOABI4 diff --git a/clang/test/Driver/mingw.cpp b/clang/test/Driver/mingw.cpp index 4a9ba4d259b46fff054106f07ea64166a34710bf..9790c86a364f850a6a0a2c600a4392916d43c032 100644 --- a/clang/test/Driver/mingw.cpp +++ b/clang/test/Driver/mingw.cpp @@ -84,3 +84,7 @@ // RUN: %clang --target=arm64ec-windows-gnu -### -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK_MINGW_EC_LINK // CHECK_MINGW_EC_LINK: "-m" "arm64ecpe" + +// RUN: %clang --target=i686-windows-gnu -fms-hotpatch -### -- %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=FUNCTIONPADMIN +// FUNCTIONPADMIN: "--functionpadmin" diff --git a/clang/test/Driver/module-output.cppm b/clang/test/Driver/module-output.cppm index bf7bfbf3cb5740247fbda2e805dd71c95f412e7d..7cf0771f3d6eff8aad4efa0efdc2997b607fa378 100644 --- a/clang/test/Driver/module-output.cppm +++ b/clang/test/Driver/module-output.cppm @@ -42,7 +42,7 @@ export module Hello; // CHECK: "-emit-module-interface" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/output/Hello.pcm" "-x" "c++" "{{.*}}/Hello.cppm" // CHECK: "-emit-obj" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/output/Hello.o" "-x" "pcm" "{{.*}}/output/Hello.pcm" -// MULTIPLE-ARCH: option '-fmodule-output' can't be used with multiple arch options +// MULTIPLE-ARCH: option '-fmodule-output' cannot be used with multiple arch options // CHECK-SPECIFIED: "-emit-module-interface" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/pcm/Hello.pcm" "-x" "c++" "{{.*}}/Hello.cppm" // CHECK-SPECIFIED: "-emit-obj" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/Hello.o" "-x" "pcm" "{{.*}}/pcm/Hello.pcm" diff --git a/clang/test/Driver/msp430-char.c b/clang/test/Driver/msp430-char.c new file mode 100644 index 0000000000000000000000000000000000000000..67954e3e2a1be5fb593a2c663f479dbd2cf8f280 --- /dev/null +++ b/clang/test/Driver/msp430-char.c @@ -0,0 +1,4 @@ +/// Check that char is unsigned by default. +// RUN: %clang -### %s --target=msp430 -c 2>&1 | FileCheck %s +// CHECK: "-cc1" "-triple" "msp430" +// CHECK-SAME: "-fno-signed-char" diff --git a/clang/test/Driver/nvptx-cuda-system-arch.c b/clang/test/Driver/nvptx-cuda-system-arch.c index 6a8a218406d1393e6164b8a02b964ff3ad6e2a4b..c54eeac73f73b5badd3d3fa6a04b3085bbcc4932 100644 --- a/clang/test/Driver/nvptx-cuda-system-arch.c +++ b/clang/test/Driver/nvptx-cuda-system-arch.c @@ -1,5 +1,5 @@ -// REQUIRES: system-linux // REQUIRES: shell +// XFAIL: target={{.*}}-zos{{.*}} // RUN: mkdir -p %t // RUN: cp %S/Inputs/nvptx-arch/nvptx_arch_fail %t/ diff --git a/clang/test/Driver/openmp-system-arch.c b/clang/test/Driver/openmp-system-arch.c index cd49f4600996664842311f4f4f54eb58abc96c0e..d097c6bc065484b882a65e330c59be1402f981a0 100644 --- a/clang/test/Driver/openmp-system-arch.c +++ b/clang/test/Driver/openmp-system-arch.c @@ -1,5 +1,5 @@ -// REQUIRES: system-linux // REQUIRES: shell +// XFAIL: target={{.*}}-zos{{.*}} // RUN: mkdir -p %t // RUN: cp %S/Inputs/amdgpu-arch/amdgpu_arch_fail %t/ diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c index 03eacf99736f9e1de5c5f3ea06cb9f221f68873f..09d499548aa565577f14f5eb046a0d30b8cc2a01 100644 --- a/clang/test/Driver/print-supported-extensions-aarch64.c +++ b/clang/test/Driver/print-supported-extensions-aarch64.c @@ -77,17 +77,18 @@ // CHECK-NEXT: profile FEAT_SPE Enable Statistical Profiling extension // CHECK-NEXT: predres2 FEAT_SPECRES2 Enable Speculation Restriction Instruction // CHECK-NEXT: ssbs FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit -// CHECK-NEXT: ssve-aes FEAT_SSVE_AES Enable Armv9.6-A SVE2 AES support in streaming SVE mode +// CHECK-NEXT: ssve-aes FEAT_SSVE_AES Enable Armv9.6-A SVE AES support in streaming SVE mode // CHECK-NEXT: ssve-fp8dot2 FEAT_SSVE_FP8DOT2 Enable SVE2 FP8 2-way dot product instructions // CHECK-NEXT: ssve-fp8dot4 FEAT_SSVE_FP8DOT4 Enable SVE2 FP8 4-way dot product instructions // CHECK-NEXT: ssve-fp8fma FEAT_SSVE_FP8FMA Enable SVE2 FP8 multiply-add instructions // CHECK-NEXT: sve FEAT_SVE Enable Scalable Vector Extension (SVE) instructions -// CHECK-NEXT: sve-aes2 FEAT_SVE_AES2 Enable Armv9.6-A SVE multi-vector AES and 128-bit PMULL instructions +// CHECK-NEXT: sve-aes FEAT_SVE_AES, FEAT_SVE_PMULL128 Enable SVE AES and quadword SVE polynomial multiply instructions +// CHECK-NEXT: sve-aes2 FEAT_SVE_AES2 Enable Armv9.6-A SVE multi-vector AES and multi-vector quadword polynomial multiply instructions // CHECK-NEXT: sve-b16b16 FEAT_SVE_B16B16 Enable SVE2 non-widening and SME2 Z-targeting non-widening BFloat16 instructions // CHECK-NEXT: sve-bfscale FEAT_SVE_BFSCALE Enable Armv9.6-A SVE BFloat16 scaling instructions // CHECK-NEXT: sve-f16f32mm FEAT_SVE_F16F32MM Enable Armv9.6-A FP16 to FP32 Matrix Multiply // CHECK-NEXT: sve2 FEAT_SVE2 Enable Scalable Vector Extension 2 (SVE2) instructions -// CHECK-NEXT: sve2-aes FEAT_SVE_AES, FEAT_SVE_PMULL128 Enable AES SVE2 instructions +// CHECK-NEXT: sve2-aes Shorthand for +sve2+sve-aes // CHECK-NEXT: sve2-bitperm FEAT_SVE_BitPerm Enable bit permutation SVE2 instructions // CHECK-NEXT: sve2-sha3 FEAT_SVE_SHA3 Enable SHA3 SVE2 instructions // CHECK-NEXT: sve2-sm4 FEAT_SVE_SM4 Enable SM4 SVE2 instructions diff --git a/clang/test/Driver/ps5-linker.c b/clang/test/Driver/ps5-linker.c index 95267942edc1723622aba2868e22dbb6ba33729f..62aa3a40e455af1004a84c18c819ab4472454088 100644 --- a/clang/test/Driver/ps5-linker.c +++ b/clang/test/Driver/ps5-linker.c @@ -67,12 +67,14 @@ // CHECK-NO-EXE-NOT: "--unresolved-symbols // CHECK-NO-EXE-NOT: "-z" -// Test that an appropriate linker script is supplied by the driver. +// Test that an appropriate linker script is supplied by the driver, but can +// be overridden with -T. // RUN: %clang --target=x86_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-SCRIPT -DSCRIPT=main %s // RUN: %clang --target=x86_64-sie-ps5 %s -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-SCRIPT -DSCRIPT=prx %s // RUN: %clang --target=x86_64-sie-ps5 %s -static -### 2>&1 | FileCheck --check-prefixes=CHECK-SCRIPT -DSCRIPT=static %s // RUN: %clang --target=x86_64-sie-ps5 %s -r -### 2>&1 | FileCheck --check-prefixes=CHECK-NO-SCRIPT %s +// RUN: %clang --target=x86_64-sie-ps5 %s -T custom.script -### 2>&1 | FileCheck --check-prefixes=CHECK-CUSTOM-SCRIPT --implicit-check-not "\"{{-T|--script|--default-script}}\"" %s // CHECK-SCRIPT: {{ld(\.exe)?}}" // CHECK-SCRIPT-SAME: "--default-script" "[[SCRIPT]].script" @@ -80,6 +82,9 @@ // CHECK-NO-SCRIPT: {{ld(\.exe)?}}" // CHECK-NO-SCRIPT-NOT: "--default-script" +// CHECK-CUSTOM-SCRIPT: {{ld(\.exe)?}}" +// CHECK-CUSTOM-SCRIPT-SAME: "-T" "custom.script" + // Test that -static is forwarded to the linker // RUN: %clang --target=x86_64-sie-ps5 -static %s -### 2>&1 | FileCheck --check-prefixes=CHECK-STATIC %s @@ -97,6 +102,60 @@ // Check the default library name. // CHECK-JMC: "--push-state" "--whole-archive" "-lSceJmc_nosubmission" "--pop-state" +// Test that CRT objects and libraries are supplied to the linker and can be +// omitted with -noxxx options. These switches have some interaction with +// sanitizer RT libraries. That's checked in fsanitize.c + +// RUN: %clang --target=x86_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN-CRT,CHECK-DYNAMIC-LIBC,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-SHARED-CRT,CHECK-DYNAMIC-LIBC,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-CRT,CHECK-STATIC-LIBCPP,CHECK-STATIC-LIBC,CHECK-STATIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -r -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-NO-LIBS %s + +// RUN: %clang --target=x86_64-sie-ps5 %s -pthread -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-PTHREAD %s + +// RUN: %clang --target=x86_64-sie-ps5 %s -nostartfiles -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-DYNAMIC-LIBC,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nostartfiles -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-DYNAMIC-LIBC,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nostartfiles -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-STATIC-LIBCPP,CHECK-STATIC-LIBC,CHECK-STATIC-CORE-LIBS %s + +// RUN: %clang --target=x86_64-sie-ps5 %s -nodefaultlibs -pthread -fjmc -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN-CRT,CHECK-NO-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nodefaultlibs -pthread -fjmc -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-SHARED-CRT,CHECK-NO-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nodefaultlibs -pthread -fjmc -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-CRT,CHECK-NO-LIBS %s + +// RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib -pthread -fjmc -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-NO-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib -pthread -fjmc -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-NO-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib -pthread -fjmc -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-NO-CRT,CHECK-NO-LIBS %s + +// RUN: %clang --target=x86_64-sie-ps5 %s -nolibc -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN-CRT,CHECK-NO-LIBC,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nolibc -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-SHARED-CRT,CHECK-NO-LIBC,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nolibc -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-CRT,CHECK-STATIC-LIBCPP,CHECK-NO-LIBC,CHECK-STATIC-CORE-LIBS %s + +// RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib++ -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-MAIN-CRT,CHECK-NO-LIBCPP,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib++ -shared -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-SHARED-CRT,CHECK-NO-LIBCPP,CHECK-DYNAMIC-CORE-LIBS %s +// RUN: %clang --target=x86_64-sie-ps5 %s -nostdlib++ -static -### 2>&1 | FileCheck --check-prefixes=CHECK-LD,CHECK-STATIC-CRT,CHECK-NO-LIBCPP,CHECK-STATIC-LIBC,CHECK-STATIC-CORE-LIBS %s + +// CHECK-LD: {{ld(\.exe)?}}" +// CHECK-MAIN-CRT-SAME: "crt1.o" "crti.o" "crtbegin.o" +// CHECK-SHARED-CRT-SAME: "crti.o" "crtbeginS.o" +// CHECK-STATIC-CRT-SAME: "crt1.o" "crti.o" "crtbeginT.o" + +// CHECK-NO-LIBC-NOT: "-lc{{(_stub_weak)?}}" +// CHECK-NO-LIBCPP-NOT: "-l{{c_stub_weak|stdc\+\+}}" + +// CHECK-DYNAMIC-LIBC-SAME: "-lc_stub_weak" +// CHECK-DYNAMIC-CORE-LIBS-SAME: "-lkernel_stub_weak" +// CHECK-STATIC-LIBCPP-SAME: "-lstdc++" +// CHECK-STATIC-LIBC-SAME: "-lm" "-lc" +// CHECK-STATIC-CORE-LIBS-SAME: "-lcompiler_rt" "-lkernel" + +// CHECK-PTHREAD-SAME: "-lpthread" + +// CHECK-MAIN-CRT-SAME: "crtend.o" "crtn.o" +// CHECK-SHARED-CRT-SAME: "crtendS.o" "crtn.o" +// CHECK-STATIC-CRT-SAME: "crtend.o" "crtn.o" + +// CHECK-NO-CRT-NOT: "crt{{[^"]*}}.o" +// CHECK-NO-LIBS-NOT: "-l{{[^"]*}}" + // Test the driver's control over the -fcrash-diagnostics-dir behavior with linker flags. // RUN: %clang --target=x86_64-sie-ps5 -fcrash-diagnostics-dir=mydumps %s -### 2>&1 | FileCheck --check-prefixes=CHECK-DIAG %s @@ -122,7 +181,8 @@ // CHECK-LDOT-SAME: "-L." // Test that /target/lib is added to library search paths, if it -// exists and no --sysroot is specified. +// exists and no --sysroot is specified. Also confirm that CRT objects are +// found there. // RUN: rm -rf %t.dir && mkdir %t.dir // RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-NO-TARGETLIB %s @@ -132,7 +192,9 @@ // CHECK-NO-TARGETLIB-NOT: "-L{{.*[/\\]}}target/lib" // RUN: mkdir -p %t.dir/target/lib +// RUN: touch %t.dir/target/lib/crti.o // RUN: env SCE_PROSPERO_SDK_DIR=%t.dir %clang --target=x64_64-sie-ps5 %s -### 2>&1 | FileCheck --check-prefixes=CHECK-TARGETLIB %s // CHECK-TARGETLIB: {{ld(\.exe)?}}" // CHECK-TARGETLIB-SAME: "-L{{.*[/\\]}}target/lib" +// CHECK-TARGETLIB-SAME: "{{.*[/\\]}}target{{/|\\\\}}lib{{/|\\\\}}crti.o" diff --git a/clang/test/Driver/relax.s b/clang/test/Driver/relax.s index 0768a38834447fa41b8bc4a446e37ca380c429bd..7b084de7e6be29f975d272f52d9484bc5d042b4c 100644 --- a/clang/test/Driver/relax.s +++ b/clang/test/Driver/relax.s @@ -8,7 +8,7 @@ // RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s // REL: R_X86_64_REX_GOTPCRELX foo -// REL: R_X86_64_REX2_GOTPCRELX foo +// REL: R_X86_64_CODE_4_GOTPCRELX foo movq foo@GOTPCREL(%rip), %rax movq foo@GOTPCREL(%rip), %r16 diff --git a/clang/test/Driver/riscv-cpus.c b/clang/test/Driver/riscv-cpus.c index d36639d16ad4cb269fdddfaa99b5c417fd2c5688..249216612f7ee754afb09d381f482e50d1f10005 100644 --- a/clang/test/Driver/riscv-cpus.c +++ b/clang/test/Driver/riscv-cpus.c @@ -104,6 +104,68 @@ // RUN: %clang --target=riscv32 -### -c %s 2>&1 -mtune=syntacore-scr1-max | FileCheck -check-prefix=MTUNE-SYNTACORE-SCR1-MAX %s // MTUNE-SYNTACORE-SCR1-MAX: "-tune-cpu" "syntacore-scr1-max" +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -mtune=tt-ascalon-d8 | FileCheck -check-prefix=MTUNE-TT-ASCALON-D8 %s +// MTUNE-TT-ASCALON-D8: "-tune-cpu" "tt-ascalon-d8" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -mcpu=tt-ascalon-d8 | FileCheck -check-prefix=MCPU-TT-ASCALON-D8 %s +// MCPU-TT-ASCALON-D8: "-target-cpu" "tt-ascalon-d8" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+m" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+a" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+f" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+d" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+c" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+v" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+h" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zicbom" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zicbop" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zicboz" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zicntr" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zicond" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zicsr" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zifencei" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zihintntl" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zihintpause" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zihpm" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zimop" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zmmul" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zawrs" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zfa" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zfbfmin" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zfh" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zfhmin" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zca" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zcb" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zba" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zbb" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zbs" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zkt" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvbb" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvbc" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zve32f" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zve32x" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zve64d" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zve64f" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zve64x" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvfbfmin" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvfbfwma" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvfh" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvfhmin" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvkb" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvkg" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvkn" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvknc" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvkned" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvkng" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvknhb" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvkt" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvl128b" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvl256b" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvl32b" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+zvl64b" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+svinval" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+svnapot" +// MCPU-TT-ASCALON-D8-SAME: "-target-feature" "+svpbmt" + // RUN: %clang --target=riscv64 -### -c %s 2>&1 -mcpu=veyron-v1 | FileCheck -check-prefix=MCPU-VEYRON-V1 %s // MCPU-VEYRON-V1: "-target-cpu" "veyron-v1" // MCPU-VEYRON-V1: "-target-feature" "+m" diff --git a/clang/test/Driver/x86-march.c b/clang/test/Driver/x86-march.c index 3bc2a82ae778d6b8e22ea98bbc1e0d05442c46a1..341f01c8d668dfd5c448949785cb35b45c842b54 100644 --- a/clang/test/Driver/x86-march.c +++ b/clang/test/Driver/x86-march.c @@ -120,6 +120,10 @@ // RUN: | FileCheck %s -check-prefix=clearwaterforest // clearwaterforest: "-target-cpu" "clearwaterforest" // +// RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=diamondrapids 2>&1 \ +// RUN: | FileCheck %s -check-prefix=diamondrapids +// diamondrapids: "-target-cpu" "diamondrapids" +// // RUN: %clang -target x86_64-unknown-unknown -c -### %s -march=lakemont 2>&1 \ // RUN: | FileCheck %s -check-prefix=lakemont // lakemont: "-target-cpu" "lakemont" diff --git a/clang/test/Frontend/noderef.cpp b/clang/test/Frontend/noderef.cpp index 68342a8e6467b8b3b2a71b38f4b5edfbf01a070f..44c11da0dc56a0fe5b8bf0ac6f81299e4be1fcbf 100644 --- a/clang/test/Frontend/noderef.cpp +++ b/clang/test/Frontend/noderef.cpp @@ -183,3 +183,8 @@ int *const_cast_check(NODEREF const int *x) { const int *const_cast_check(NODEREF int *x) { return const_cast(x); // expected-warning{{casting to dereferenceable pointer removes 'noderef' attribute}} } + +namespace GH116124 { +// This declaration would previously cause a failed assertion. +int *_Atomic a __attribute__((noderef)); +} diff --git a/clang/test/Headers/limits.cpp b/clang/test/Headers/limits.cpp index da7a64901831d56803c127e195648adb6d0a2428..132e5bc24a0c929e792207d2b599f09b116e0f46 100644 --- a/clang/test/Headers/limits.cpp +++ b/clang/test/Headers/limits.cpp @@ -4,6 +4,9 @@ // RUN: %clang_cc1 -std=c17 -ffreestanding -fsyntax-only -verify -x c %s // RUN: %clang_cc1 -std=c2x -ffreestanding -fsyntax-only -verify -x c %s +// Specifically test arm64 linux platforms. +// RUN: %clang_cc1 -triple arm64-linux -ffreestanding -fsyntax-only -verify -x c %s + // Specifically test 16-bit int platforms. // RUN: %clang_cc1 -triple=avr -ffreestanding -fsyntax-only -verify -x c %s // RUN: %clang_cc1 -triple=avr -std=c++11 -ffreestanding -fsyntax-only -verify %s diff --git a/clang/test/Misc/pragma-attribute-strict-subjects.c b/clang/test/Misc/pragma-attribute-strict-subjects.c index 7c2548c7dfc26b9a6ae819b8318cc9131675ade1..807977fb252aa6c021eada961b3dd61a2675fb69 100644 --- a/clang/test/Misc/pragma-attribute-strict-subjects.c +++ b/clang/test/Misc/pragma-attribute-strict-subjects.c @@ -51,7 +51,7 @@ struct testRecoverStrictnessStruct { }; #pragma clang attribute pop #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} int testRecoverExtraVar = 0; // CHECK-LABEL: VarDecl{{.*}} testRecoverExtraVar @@ -188,7 +188,7 @@ struct testSubset7Struct { }; #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum_constant', and 'enum'}} int testSubsetRecoverVar; // CHECK-LABEL: VarDecl{{.*}} testSubsetRecoverVar @@ -205,7 +205,7 @@ struct testSubsetRecoverStruct { }; #pragma clang attribute pop #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} int testSubsetNoVar; // CHECK-LABEL: VarDecl{{.*}} testSubsetNoVar diff --git a/clang/test/Misc/target-invalid-cpu-note/amdgcn.c b/clang/test/Misc/target-invalid-cpu-note/amdgcn.c index b3ddbd53a0391b2dc561e5d0a39a6df842517d64..642d2df211c21a0ee40f05efa7cd4daf1596f914 100644 --- a/clang/test/Misc/target-invalid-cpu-note/amdgcn.c +++ b/clang/test/Misc/target-invalid-cpu-note/amdgcn.c @@ -48,6 +48,7 @@ // CHECK-SAME: {{^}}, gfx940 // CHECK-SAME: {{^}}, gfx941 // CHECK-SAME: {{^}}, gfx942 +// CHECK-SAME: {{^}}, gfx950 // CHECK-SAME: {{^}}, gfx1010 // CHECK-SAME: {{^}}, gfx1011 // CHECK-SAME: {{^}}, gfx1012 @@ -74,4 +75,5 @@ // CHECK-SAME: {{^}}, gfx10-3-generic // CHECK-SAME: {{^}}, gfx11-generic // CHECK-SAME: {{^}}, gfx12-generic +// CHECK-SAME: {{^}}, gfx9-4-generic // CHECK-SAME: {{$}} diff --git a/clang/test/Misc/target-invalid-cpu-note/nvptx.c b/clang/test/Misc/target-invalid-cpu-note/nvptx.c index a59e1c6fab1c49b68a6377604d6e70a303481336..3ea6c02d6b38469e1f0fa970e355e7508ee01e4e 100644 --- a/clang/test/Misc/target-invalid-cpu-note/nvptx.c +++ b/clang/test/Misc/target-invalid-cpu-note/nvptx.c @@ -50,9 +50,11 @@ // CHECK-SAME: {{^}}, gfx909 // CHECK-SAME: {{^}}, gfx90a // CHECK-SAME: {{^}}, gfx90c +// CHECK-SAME: {{^}}, gfx9-4-generic // CHECK-SAME: {{^}}, gfx940 // CHECK-SAME: {{^}}, gfx941 // CHECK-SAME: {{^}}, gfx942 +// CHECK-SAME: {{^}}, gfx950 // CHECK-SAME: {{^}}, gfx10-1-generic // CHECK-SAME: {{^}}, gfx1010 // CHECK-SAME: {{^}}, gfx1011 diff --git a/clang/test/Misc/target-invalid-cpu-note/riscv.c b/clang/test/Misc/target-invalid-cpu-note/riscv.c index 219f173bf0f45359f4acdec105c9fb42ee868ccd..7b72e0f2405bf241d2f55bb58a9325355e0b72be 100644 --- a/clang/test/Misc/target-invalid-cpu-note/riscv.c +++ b/clang/test/Misc/target-invalid-cpu-note/riscv.c @@ -42,6 +42,7 @@ // RISCV64-SAME: {{^}}, syntacore-scr4-rv64 // RISCV64-SAME: {{^}}, syntacore-scr5-rv64 // RISCV64-SAME: {{^}}, syntacore-scr7 +// RISCV64-SAME: {{^}}, tt-ascalon-d8 // RISCV64-SAME: {{^}}, veyron-v1 // RISCV64-SAME: {{^}}, xiangshan-nanhu // RISCV64-SAME: {{$}} @@ -89,6 +90,7 @@ // TUNE-RISCV64-SAME: {{^}}, syntacore-scr4-rv64 // TUNE-RISCV64-SAME: {{^}}, syntacore-scr5-rv64 // TUNE-RISCV64-SAME: {{^}}, syntacore-scr7 +// TUNE-RISCV64-SAME: {{^}}, tt-ascalon-d8 // TUNE-RISCV64-SAME: {{^}}, veyron-v1 // TUNE-RISCV64-SAME: {{^}}, xiangshan-nanhu // TUNE-RISCV64-SAME: {{^}}, generic diff --git a/clang/test/Misc/target-invalid-cpu-note/x86.c b/clang/test/Misc/target-invalid-cpu-note/x86.c index 7879676040af46a3f68439ea73152c17a52122aa..f89cdc2aa573ff737d067dbb2c3e1fd91163d622 100644 --- a/clang/test/Misc/target-invalid-cpu-note/x86.c +++ b/clang/test/Misc/target-invalid-cpu-note/x86.c @@ -69,6 +69,7 @@ // X86-SAME: {{^}}, graniterapids-d // X86-SAME: {{^}}, emeraldrapids // X86-SAME: {{^}}, clearwaterforest +// X86-SAME: {{^}}, diamondrapids // X86-SAME: {{^}}, knl // X86-SAME: {{^}}, knm // X86-SAME: {{^}}, lakemont @@ -155,6 +156,7 @@ // X86_64-SAME: {{^}}, graniterapids-d // X86_64-SAME: {{^}}, emeraldrapids // X86_64-SAME: {{^}}, clearwaterforest +// X86_64-SAME: {{^}}, diamondrapids // X86_64-SAME: {{^}}, knl // X86_64-SAME: {{^}}, knm // X86_64-SAME: {{^}}, k8 @@ -250,6 +252,7 @@ // TUNE_X86-SAME: {{^}}, graniterapids-d // TUNE_X86-SAME: {{^}}, emeraldrapids // TUNE_X86-SAME: {{^}}, clearwaterforest +// TUNE_X86-SAME: {{^}}, diamondrapids // TUNE_X86-SAME: {{^}}, knl // TUNE_X86-SAME: {{^}}, knm // TUNE_X86-SAME: {{^}}, lakemont @@ -352,6 +355,7 @@ // TUNE_X86_64-SAME: {{^}}, graniterapids-d // TUNE_X86_64-SAME: {{^}}, emeraldrapids // TUNE_X86_64-SAME: {{^}}, clearwaterforest +// TUNE_X86_64-SAME: {{^}}, diamondrapids // TUNE_X86_64-SAME: {{^}}, knl // TUNE_X86_64-SAME: {{^}}, knm // TUNE_X86_64-SAME: {{^}}, lakemont diff --git a/clang/test/Modules/no-eager-load.cppm b/clang/test/Modules/no-eager-load.cppm index c9eddaaed155524f773db9ae5070f77c0199d40b..aa6de44c998f36caa4a407e3435846bca73f38e4 100644 --- a/clang/test/Modules/no-eager-load.cppm +++ b/clang/test/Modules/no-eager-load.cppm @@ -44,7 +44,7 @@ void use() { // expected-note@* {{but in 'a' found a different body}} } -// expected-error@a.cppm:* {{declaration 'foo' attached to named module 'a' can't be attached to other modules}} +// expected-error@a.cppm:* {{declaration 'foo' attached to named module 'a' cannot be attached to other modules}} // expected-note@b.cppm:* {{}} //--- h.cppm @@ -59,5 +59,5 @@ void use() { // expected-note@* {{but in 'a' found a different body}} } -// expected-error@a.cppm:* {{declaration 'foo' attached to named module 'a' can't be attached to other modules}} +// expected-error@a.cppm:* {{declaration 'foo' attached to named module 'a' cannot be attached to other modules}} // expected-note@b.cppm:* {{}} diff --git a/clang/test/Modules/same-decl-in-different-modules.cppm b/clang/test/Modules/same-decl-in-different-modules.cppm index 2e8e90f7cd8e9508536539b24d5684c85e0777d0..8ad9e29051d4e54b0309802c138db9776aae0e45 100644 --- a/clang/test/Modules/same-decl-in-different-modules.cppm +++ b/clang/test/Modules/same-decl-in-different-modules.cppm @@ -32,11 +32,11 @@ void test() { S s; } -// expected-error@mod1.cppm:* {{declaration 'v' attached to named module 'mod1' can't be attached to other modules}} +// expected-error@mod1.cppm:* {{declaration 'v' attached to named module 'mod1' cannot be attached to other modules}} // expected-note@mod2.cppm:* {{}} -// expected-error@mod1.cppm:* {{declaration 'func' attached to named module 'mod1' can't be attached to other modules}} +// expected-error@mod1.cppm:* {{declaration 'func' attached to named module 'mod1' cannot be attached to other modules}} // expected-note@mod2.cppm:* {{}} -// expected-error@mod1.cppm:* {{declaration 'A' attached to named module 'mod1' can't be attached to other modules}} +// expected-error@mod1.cppm:* {{declaration 'A' attached to named module 'mod1' cannot be attached to other modules}} // expected-note@mod2.cppm:* {{}} -// expected-error@mod1.cppm:* 1+{{declaration 'S' attached to named module 'mod1' can't be attached to other modules}} +// expected-error@mod1.cppm:* 1+{{declaration 'S' attached to named module 'mod1' cannot be attached to other modules}} // expected-note@mod2.cppm:* 1+{{}} diff --git a/clang/test/OpenMP/for_simd_loop_messages.cpp b/clang/test/OpenMP/for_simd_loop_messages.cpp index 1cc5988ea8092f4d8d5dee27a96b2f5c83efbffc..74a52f3f5d694fe7bc869c984905b32ba438fe12 100644 --- a/clang/test/OpenMP/for_simd_loop_messages.cpp +++ b/clang/test/OpenMP/for_simd_loop_messages.cpp @@ -731,7 +731,7 @@ void test_ordered() { for (int i = 0; i < 16; ++i) ; #pragma omp parallel -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp for simd' directive}} #pragma omp for simd ordered(1) for (int i = 0; i < 16; ++i) ; diff --git a/clang/test/OpenMP/masked_taskloop_simd_linear_messages.cpp b/clang/test/OpenMP/masked_taskloop_simd_linear_messages.cpp index 50d2da7e8fd4da1a1dae64b0d67afd898ea4777f..6072ad1b92445296f637f62a6080e45b20851f31 100644 --- a/clang/test/OpenMP/masked_taskloop_simd_linear_messages.cpp +++ b/clang/test/OpenMP/masked_taskloop_simd_linear_messages.cpp @@ -152,7 +152,7 @@ template int foomain(I argc, C **argv) { #pragma omp masked taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}} for (int k = 0; k < argc; ++k) ++k; #if defined(OMP52) - // omp52-error@+3{{step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier}} + // omp52-error@+3{{step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier}} // expected-error@+2 {{linear variable with incomplete type 'S1'}} // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}} #pragma omp masked taskloop simd linear (a, b: val, B::ib) diff --git a/clang/test/OpenMP/master_taskloop_simd_linear_messages.cpp b/clang/test/OpenMP/master_taskloop_simd_linear_messages.cpp index ee29f63e110c01780269c4030066a2c1dfe3eaf5..c1bf61b8183ec506a13c6f1233fee6e6dca85387 100644 --- a/clang/test/OpenMP/master_taskloop_simd_linear_messages.cpp +++ b/clang/test/OpenMP/master_taskloop_simd_linear_messages.cpp @@ -152,7 +152,7 @@ template int foomain(I argc, C **argv) { #pragma omp master taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}} for (int k = 0; k < argc; ++k) ++k; #if defined(OMP52) - // omp52-error@+3{{step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier}} + // omp52-error@+3{{step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier}} // expected-error@+2 {{linear variable with incomplete type 'S1'}} // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}} #pragma omp master taskloop simd linear (a, b: val, B::ib) diff --git a/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp index f55453f6e8e15a11d155a97378b3694c7150e4ea..4760a0281df54021f27e3d52ea680cf02f675b0d 100644 --- a/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp @@ -638,7 +638,7 @@ void test_ordered() { #pragma omp parallel for simd ordered for (int i = 0; i < 16; ++i) ; -//expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp parallel for simd' directive}} +//expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp parallel for simd' directive}} #pragma omp parallel for simd ordered(1) for (int i = 0; i < 16; ++i) ; diff --git a/clang/test/OpenMP/parallel_for_simd_messages.cpp b/clang/test/OpenMP/parallel_for_simd_messages.cpp index 8237406a1c068aba157db06fd0a2e50a2533099e..b3408fab4417f822fe7dd295fd6f14dcbcd589dd 100644 --- a/clang/test/OpenMP/parallel_for_simd_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_messages.cpp @@ -94,7 +94,7 @@ void test_ordered() { #pragma omp parallel for simd ordered for (int i = 0; i < 16; ++i) ; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp parallel for simd' directive}} #pragma omp parallel for simd ordered(1) for (int i = 0; i < 16; ++i) ; diff --git a/clang/test/OpenMP/parallel_masked_taskloop_simd_linear_messages.cpp b/clang/test/OpenMP/parallel_masked_taskloop_simd_linear_messages.cpp index a913a4e3319644229fc27e0c5bf5459b46161ee4..bda3ef09181a69e31bc6f69fea23ed27e3f48a0b 100644 --- a/clang/test/OpenMP/parallel_masked_taskloop_simd_linear_messages.cpp +++ b/clang/test/OpenMP/parallel_masked_taskloop_simd_linear_messages.cpp @@ -152,7 +152,7 @@ template int foomain(I argc, C **argv) { #pragma omp parallel masked taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}} for (int k = 0; k < argc; ++k) ++k; #if defined(OMP52) - // omp52-error@+3{{step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier}} + // omp52-error@+3{{step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier}} // expected-error@+2 {{linear variable with incomplete type 'S1'}} // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}} #pragma omp parallel masked taskloop simd linear (a, b: val, B::ib) diff --git a/clang/test/OpenMP/parallel_master_taskloop_simd_linear_messages.cpp b/clang/test/OpenMP/parallel_master_taskloop_simd_linear_messages.cpp index 2be29fdc6b92951405f60166400bcf84ed78d73a..01a734cd927e27b1ff586c4e126c245e11ff662b 100644 --- a/clang/test/OpenMP/parallel_master_taskloop_simd_linear_messages.cpp +++ b/clang/test/OpenMP/parallel_master_taskloop_simd_linear_messages.cpp @@ -152,7 +152,7 @@ template int foomain(I argc, C **argv) { #pragma omp parallel master taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}} for (int k = 0; k < argc; ++k) ++k; #if defined(OMP52) - // omp52-error@+3{{step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier}} + // omp52-error@+3{{step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier}} // expected-error@+2 {{linear variable with incomplete type 'S1'}} // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}} #pragma omp parallel master taskloop simd linear (a, b: val, B::ib) diff --git a/clang/test/OpenMP/simd_linear_messages.cpp b/clang/test/OpenMP/simd_linear_messages.cpp index a19fad9d7718a0f6ca69f9a0fb5f06dd20486473..68a2999fdf65a4e286983af9c9659ceff5b4a435 100644 --- a/clang/test/OpenMP/simd_linear_messages.cpp +++ b/clang/test/OpenMP/simd_linear_messages.cpp @@ -142,7 +142,7 @@ template int foomain(I argc, C **argv) { #pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}} for (int k = 0; k < argc; ++k) ++k; #if defined(OMP52) - // omp52-error@+3{{step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier}} + // omp52-error@+3{{step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier}} // expected-error@+2 {{linear variable with incomplete type 'S1'}} // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}} #pragma omp simd linear (a, b: val, B::ib) diff --git a/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp index 8dd7f68c25fd887c79a28094f141208487557e43..73ea96eb24278c21121561512f90b6d982591010 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp @@ -29,26 +29,26 @@ T tmain(T argc, S **argv) { #pragma omp target parallel for simd ordered() // expected-error {{expected expression}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+2 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+2 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} // expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}} #pragma omp target parallel for simd ordered(argc for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(ST // expected-error {{expected ')'}} expected-note {{to match this '('}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(1)) // expected-warning {{extra tokens at the end of '#pragma omp target parallel for simd' are ignored}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered((ST > 0) ? 1 + ST : 2) for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; // expected-error@+3 {{argument to 'ordered' clause must be a strictly positive integer value}} // expected-error@+2 2 {{directive '#pragma omp target parallel for simd' cannot contain more than one 'ordered' clause}} -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(foobool(argc)), ordered(true), ordered(-5) for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; @@ -60,15 +60,15 @@ T tmain(T argc, S **argv) { #pragma omp target parallel for simd ordered(j = 2) // expected-error {{expected ')'}} expected-note {{to match this '('}} for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(1) for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(N) for (T i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i - ST]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(2) foo(); return argc; @@ -85,11 +85,11 @@ int main(int argc, char **argv) { #pragma omp target parallel for simd ordered() // expected-error {{expected expression}} for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i - 4]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(4 // expected-error {{expected ')'}} expected-note {{to match this '('}} for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i - 4]; -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(2 + 2)) // expected-warning {{extra tokens at the end of '#pragma omp target parallel for simd' are ignored}} for (int i = 4; i < 12; i++) argv[0][i] = argv[0][i] - argv[0][i - 4]; @@ -115,7 +115,7 @@ int main(int argc, char **argv) { // expected-error@+2 {{statement after '#pragma omp target parallel for simd' must be a for loop}} #pragma omp target parallel for simd ordered(ordered(tmain < int, char, -1, -2 > (argc, argv) // expected-error 2 {{expected ')'}} expected-note 2 {{to match this '('}} foo(); -// expected-error@+1 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}} +// expected-error@+1 {{'ordered' clause with a parameter cannot be specified in '#pragma omp target parallel for simd' directive}} #pragma omp target parallel for simd ordered(2) foo(); return tmain(argc, argv); diff --git a/clang/test/OpenMP/taskloop_simd_linear_messages.cpp b/clang/test/OpenMP/taskloop_simd_linear_messages.cpp index 22e2d26cb556169204a6a3acd7da8de26ee42f54..5bf4785f14be40ca95777310e0f64e4835223cbc 100644 --- a/clang/test/OpenMP/taskloop_simd_linear_messages.cpp +++ b/clang/test/OpenMP/taskloop_simd_linear_messages.cpp @@ -152,7 +152,7 @@ template int foomain(I argc, C **argv) { #pragma omp taskloop simd linear (S1) // expected-error {{'S1' does not refer to a value}} for (int k = 0; k < argc; ++k) ++k; #if defined(OMP52) - // omp52-error@+3{{step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier}} + // omp52-error@+3{{step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier}} // expected-error@+2 {{linear variable with incomplete type 'S1'}} // expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S2'}} #pragma omp taskloop simd linear (a, b: val, B::ib) diff --git a/clang/test/Parser/cxx2c-delete-with-message.cpp b/clang/test/Parser/cxx2c-delete-with-message.cpp index 1767a080a7dcd8e77d55b1c1cdb1edabf078991e..d2d5ccf4623c9c1abd8fb618e64f5e647a96e001 100644 --- a/clang/test/Parser/cxx2c-delete-with-message.cpp +++ b/clang/test/Parser/cxx2c-delete-with-message.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,pre26 -pedantic %s +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=expected,pre26 %s +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=expected,pre26-pedantic -pedantic %s // RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify=expected,compat -Wpre-c++26-compat %s // RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify %s @@ -7,15 +8,15 @@ struct S { void b() = delete(; // expected-error {{expected string literal}} expected-error {{expected ')'}} expected-note {{to match this '('}} void c() = delete(); // expected-error {{expected string literal}} void d() = delete(42); // expected-error {{expected string literal}} - void e() = delete("foo"[0]); // expected-error {{expected ')'}} expected-note {{to match this '('}} // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - void f() = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - - S() = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - ~S() = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - S(const S&) = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - S(S&&) = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - S& operator=(const S&) = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} - S& operator=(S&&) = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + void e() = delete("foo"[0]); // expected-error {{expected ')'}} expected-note {{to match this '('}} // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + void f() = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + + S() = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + ~S() = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + S(const S&) = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + S(S&&) = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + S& operator=(const S&) = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} + S& operator=(S&&) = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} }; struct T { @@ -31,8 +32,8 @@ void a() = delete; void b() = delete(; // expected-error {{expected string literal}} expected-error {{expected ')'}} expected-note {{to match this '('}} void c() = delete(); // expected-error {{expected string literal}} void d() = delete(42); // expected-error {{expected string literal}} -void e() = delete("foo"[0]); // expected-error {{expected ')'}} expected-note {{to match this '('}} // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} -void f() = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} +void e() = delete("foo"[0]); // expected-error {{expected ')'}} expected-note {{to match this '('}} // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} +void f() = delete("foo"); // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}} constexpr const char *getMsg() { return "this is a message"; } void func() = delete(getMsg()); // expected-error {{expected string literal}} @@ -49,3 +50,12 @@ struct C { U f = delete ("hello"); // expected-error {{cannot delete expression of type 'const char[6]'}} }; } + +namespace GH109311 { +void f() = delete +#if __cpp_deleted_function >= 202403L + ("reason") // pre26-pedantic-warning {{'= delete' with a message is a C++2c extension}} \ + // compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2}} +#endif +; +} diff --git a/clang/test/Parser/pragma-attribute.cpp b/clang/test/Parser/pragma-attribute.cpp index 6377fc754352e7aeb9189a7ac7d3a9391845af78..d5b1f848abd06f3b375c960b17e02adb1cd39442 100644 --- a/clang/test/Parser/pragma-attribute.cpp +++ b/clang/test/Parser/pragma-attribute.cpp @@ -124,7 +124,7 @@ void function(); #pragma clang attribute push (__attribute__((annotate)), apply_to=function foo) // expected-error {{extra tokens after attribute in a '#pragma clang attribute push'}} #pragma clang attribute push (__attribute__((objc_bridge_related)), apply_to=function) -// expected-error@-1 {{attribute 'objc_bridge_related' can't be applied to 'function'}} +// expected-error@-1 {{attribute 'objc_bridge_related' cannot be applied to 'function'}} #pragma clang attribute pop #pragma clang attribute push (__attribute__((objc_bridge_related(1))), apply_to=function) // expected-error {{expected a related Objective-C class name, e.g., 'NSColor'}} @@ -182,15 +182,15 @@ _Pragma("clang attribute pop"); #pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_local)) #pragma clang attribute pop -#pragma clang attribute push([[clang::uninitialized]], apply_to = function) // expected-error {{attribute 'uninitialized' can't be applied to 'function'}} +#pragma clang attribute push([[clang::uninitialized]], apply_to = function) // expected-error {{attribute 'uninitialized' cannot be applied to 'function'}} #pragma clang attribute pop -#pragma clang attribute push([[clang::uninitialized]], apply_to = variable) // expected-error {{attribute 'uninitialized' can't be applied to 'variable'}} +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable) // expected-error {{attribute 'uninitialized' cannot be applied to 'variable'}} #pragma clang attribute pop -#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_thread_local)) // expected-error {{attribute 'uninitialized' can't be applied to 'variable(is_thread_local)'}} +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_thread_local)) // expected-error {{attribute 'uninitialized' cannot be applied to 'variable(is_thread_local)'}} #pragma clang attribute pop -#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_global)) // expected-error {{attribute 'uninitialized' can't be applied to 'variable(is_global)'}} +#pragma clang attribute push([[clang::uninitialized]], apply_to = variable(is_global)) // expected-error {{attribute 'uninitialized' cannot be applied to 'variable(is_global)'}} #pragma clang attribute pop -#pragma clang attribute push([[clang::uninitialized]], apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) // expected-error {{attribute 'uninitialized' can't be applied to 'variable(is_parameter)', and 'variable(unless(is_parameter))'}} +#pragma clang attribute push([[clang::uninitialized]], apply_to = any(variable(is_parameter), variable(unless(is_parameter)))) // expected-error {{attribute 'uninitialized' cannot be applied to 'variable(is_parameter)', and 'variable(unless(is_parameter))'}} #pragma clang attribute pop // We're allowed to apply attributes to subsets of allowed subjects. #pragma clang attribute push([[clang::no_destroy]], apply_to = variable) diff --git a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl index 38d27bc21e4aa80d774d03ae9c2a34ee6e07b186..c20515716ae6b7aa59156b22d7975cad9978c5ec 100644 --- a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl +++ b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl @@ -3,7 +3,7 @@ // CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <> class RWBuffer definition implicit_instantiation // CHECK: -TemplateArgument type 'float' // CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float' -// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h '__hlsl_resource_t +// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]] // CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer @@ -13,7 +13,7 @@ RWBuffer Buffer1; // CHECK: -TemplateArgument type 'vector' // CHECK: `-ExtVectorType 0x{{[0-9a-f]+}} 'vector' 4 // CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float' -// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h '__hlsl_resource_t +// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit __handle '__hlsl_resource_t // CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)] // CHECK-SAME{LITERAL}: [[hlsl::is_rov]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c index 1f80195ecdac20ddf0f53bc9f843afcc76db349a..656b31444a9eed390f8898e1bf048ea8ecf3bdd4 100644 --- a/clang/test/ParserOpenACC/parse-clauses.c +++ b/clang/test/ParserOpenACC/parse-clauses.c @@ -58,24 +58,21 @@ void func() { #pragma acc loop seq independent, auto for(int i = 0; i < 5;++i) {} - // expected-warning@+4{{OpenACC clause 'seq' not yet implemented, clause ignored}} - // expected-warning@+3{{OpenACC clause 'independent' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC clause 'auto' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'kernels loop' not yet implemented, pragma ignored}} + // expected-error@+3{{OpenACC clause 'independent' on 'kernels loop' construct conflicts with previous data dependence clause}} + // expected-error@+2{{OpenACC clause 'auto' on 'kernels loop' construct conflicts with previous data dependence clause}} + // expected-note@+1 2{{previous clause is here}} #pragma acc kernels loop seq independent auto for(int i = 0; i < 5;++i) {} - // expected-warning@+4{{OpenACC clause 'seq' not yet implemented, clause ignored}} - // expected-warning@+3{{OpenACC clause 'independent' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC clause 'auto' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+3{{OpenACC clause 'independent' on 'serial loop' construct conflicts with previous data dependence clause}} + // expected-error@+2{{OpenACC clause 'auto' on 'serial loop' construct conflicts with previous data dependence clause}} + // expected-note@+1 2{{previous clause is here}} #pragma acc serial loop seq, independent auto for(int i = 0; i < 5;++i) {} - // expected-warning@+4{{OpenACC clause 'seq' not yet implemented, clause ignored}} - // expected-warning@+3{{OpenACC clause 'independent' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC clause 'auto' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'parallel loop' not yet implemented, pragma ignored}} + // expected-error@+3{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-error@+2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1 2{{previous clause is here}} #pragma acc parallel loop seq independent, auto for(int i = 0; i < 5;++i) {} @@ -122,8 +119,7 @@ void func() { } void DefaultClause() { - // expected-error@+2{{expected '('}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+1{{expected '('}} #pragma acc serial loop default for(int i = 0; i < 5;++i) {} @@ -196,8 +192,7 @@ void DefaultClause() { void IfClause() { int i, j; - // expected-error@+2{{expected '('}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+1{{expected '('}} #pragma acc serial loop if for(int i = 0; i < 5;++i) {} @@ -271,74 +266,54 @@ void IfClause() { } void SelfClause() { - // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} #pragma acc serial loop self for(int i = 0; i < 5;++i) {} - // expected-warning@+3{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} - // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} #pragma acc serial loop self, seq for(int i = 0; i < 5;++i) {} - // expected-error@+4{{expected expression}} - // expected-error@+3{{expected ')'}} - // expected-note@+2{{to match this '('}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+3{{expected expression}} + // expected-error@+2{{expected ')'}} + // expected-note@+1{{to match this '('}} #pragma acc serial loop self( for(int i = 0; i < 5;++i) {} - // expected-error@+4{{use of undeclared identifier 'seq'}} - // expected-error@+3{{expected ')'}} - // expected-note@+2{{to match this '('}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+3{{use of undeclared identifier 'seq'}} + // expected-error@+2{{expected ')'}} + // expected-note@+1{{to match this '('}} #pragma acc serial loop self( seq for(int i = 0; i < 5;++i) {} - // expected-error@+5{{expected expression}} - // expected-error@+4{{use of undeclared identifier 'seq'}} - // expected-error@+3{{expected ')'}} - // expected-note@+2{{to match this '('}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+4{{expected expression}} + // expected-error@+3{{use of undeclared identifier 'seq'}} + // expected-error@+2{{expected ')'}} + // expected-note@+1{{to match this '('}} #pragma acc serial loop self(, seq for(int i = 0; i < 5;++i) {} - // expected-error@+3{{expected identifier}} - // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial loop self) for(int i = 0; i < 5;++i) {} - // expected-error@+3{{expected identifier}} - // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial loop self) seq for(int i = 0; i < 5;++i) {} - // expected-error@+3{{expected identifier}} - // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + // expected-error@+1{{expected identifier}} #pragma acc serial loop self), seq for(int i = 0; i < 5;++i) {} - // expected-error@+3{{expected expression}} - // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} - // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} + // expected-error@+1{{expected expression}} #pragma acc serial loop self(), seq for(int i = 0; i < 5;++i) {} - // expected-error@+4{{expected expression}} - // expected-error@+3{{expected expression}} - // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} - // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} + // expected-error@+2{{expected expression}} + // expected-error@+1{{expected expression}} #pragma acc serial loop self(,), seq for(int i = 0; i < 5;++i) {} - // expected-error@+3{{use of undeclared identifier 'invalid_expr'}} - // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} - // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}} + // expected-error@+1{{use of undeclared identifier 'invalid_expr'}} #pragma acc serial loop self(invalid_expr), seq for(int i = 0; i < 5;++i) {} diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c index 7a1608a6792d51784d5e959030a1786aee698455..27b9a6993fd3e89852eaca873b9e6a604c7685ea 100644 --- a/clang/test/ParserOpenACC/parse-constructs.c +++ b/clang/test/ParserOpenACC/parse-constructs.c @@ -87,32 +87,26 @@ void func() { for(int i = 0; i < 6;++i){} // expected-error@+1{{invalid OpenACC clause 'invalid'}} #pragma acc parallel invalid clause list - for(;;){} + for(int i = 0; i < 6;++i){} // expected-error@+1{{invalid OpenACC clause 'invalid'}} #pragma acc serial invalid clause list - for(;;){} - // expected-error@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'parallel loop' not yet implemented, pragma ignored}} + for(int i = 0; i < 6;++i){} + // expected-error@+1{{invalid OpenACC clause 'clause'}} #pragma acc parallel loop clause list - for(;;){} + for(int i = 0; i < 6;++i){} - // expected-warning@+1{{OpenACC construct 'parallel loop' not yet implemented, pragma ignored}} #pragma acc parallel loop - for(;;){} - // expected-error@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + for(int i = 0; i < 6;++i){} + // expected-error@+1{{invalid OpenACC clause 'clause'}} #pragma acc serial loop clause list - for(;;){} - // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}} + for(int i = 0; i < 6;++i){} #pragma acc serial loop - for(;;){} - // expected-error@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'kernels loop' not yet implemented, pragma ignored}} + for(int i = 0; i < 6;++i){} + // expected-error@+1{{invalid OpenACC clause 'clause'}} #pragma acc kernels loop clause list - for(;;){} - // expected-warning@+1{{OpenACC construct 'kernels loop' not yet implemented, pragma ignored}} + for(int i = 0; i < 6;++i){} #pragma acc kernels loop - for(;;){} + for(int i = 0; i < 6;++i){} int i = 0, j = 0, k = 0; // expected-warning@+1{{OpenACC construct 'atomic' not yet implemented, pragma ignored}} diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 418430b0b19b89eba4f48135c472e2f6ef31c529..037a3e186ee559712853b86a4e862c2346aa057c 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -227,8 +227,20 @@ // CHECK-NONEON-NOT: __ARM_FEATURE_SVE 1 // CHECK-NONEON-NOT: __ARM_NEON 1 -// RUN: %clang -target aarch64-none-linux-gnu -march=armv9-a+sve2-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv9-a+sve-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVEAES %s +// CHECK-SVEAES: __ARM_FEATURE_AES 1 + +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve2-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve-aes+sve2 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES %s +// CHECK-SVE2AES: __ARM_FEATURE_AES 1 +// CHECK-SVE2AES: __ARM_FEATURE_SVE2 1 // CHECK-SVE2AES: __ARM_FEATURE_SVE2_AES 1 + +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve2-aes+nosve2-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES-REV %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve2+sve-aes+nosve2-aes -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2AES-REV %s +// CHECK-SVE2AES-REV: __ARM_FEATURE_SVE2 1 +// CHECK-SVE2AES-REV-NOT: __ARM_FEATURE_SVE2_AES 1 + // RUN: %clang -target aarch64-none-linux-gnu -march=armv9-a+sve2-sha3 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2SHA3 %s // CHECK-SVE2SHA3: __ARM_FEATURE_SVE2_SHA3 1 // RUN: %clang -target aarch64-none-linux-gnu -march=armv9-a+sve2-sm4 -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE2SM4 %s @@ -335,7 +347,7 @@ // CHECK-MCPU-A57: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2" // CHECK-MCPU-A72: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2" // CHECK-MCPU-CORTEX-A73: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2" -// CHECK-MCPU-CORTEX-R82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8r" "-target-feature" "+ccdp" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+flagm" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+predres" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+ssbs" +// CHECK-MCPU-CORTEX-R82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8r" "-target-feature" "+ccdp" "-target-feature" "+ccpp" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+flagm" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+predres" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+ssbs" // CHECK-MCPU-M3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2" // CHECK-MCPU-M4: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2" // CHECK-MCPU-KRYO: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+neon" "-target-feature" "+perfmon" "-target-feature" "+sha2" @@ -344,7 +356,7 @@ // CHECK-MCPU-CARMEL: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8.2a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+ras" "-target-feature" "+rdm" "-target-feature" "+sha2" // RUN: %clang -target x86_64-apple-macosx -arch arm64 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64 %s -// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.4a" "-target-feature" "+aes" "-target-feature" "+altnzcv" "-target-feature" "+ccdp" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fptoint" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+predres" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+sha2" "-target-feature" "+sha3" "-target-feature" "+specrestrict" "-target-feature" "+ssbs" +// CHECK-ARCH-ARM64: "-target-cpu" "apple-m1" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.4a" "-target-feature" "+aes" "-target-feature" "+altnzcv" "-target-feature" "+ccdp" "-target-feature" "+ccpp" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+dotprod" "-target-feature" "+flagm" "-target-feature" "+fp-armv8" "-target-feature" "+fp16fml" "-target-feature" "+fptoint" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+predres" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sb" "-target-feature" "+sha2" "-target-feature" "+sha3" "-target-feature" "+specrestrict" "-target-feature" "+ssbs" // RUN: %clang -target x86_64-apple-macosx -arch arm64_32 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-ARCH-ARM64_32 %s // CHECK-ARCH-ARM64_32: "-target-cpu" "apple-s4" "-target-feature" "+zcm" "-target-feature" "+zcz" "-target-feature" "+v8.3a" "-target-feature" "+aes" "-target-feature" "+complxnum" "-target-feature" "+crc" "-target-feature" "+fp-armv8" "-target-feature" "+fullfp16" "-target-feature" "+jsconv" "-target-feature" "+lse" "-target-feature" "+neon" "-target-feature" "+pauth" "-target-feature" "+perfmon" "-target-feature" "+ras" "-target-feature" "+rcpc" "-target-feature" "+rdm" "-target-feature" "+sha2" diff --git a/clang/test/Preprocessor/predefined-arch-macros.c b/clang/test/Preprocessor/predefined-arch-macros.c index 35801e758cc58a5059fc6f5c2406908880b80c73..20aa2d4e0a54cb5d3ab49bb5d28fde12ef27219b 100644 --- a/clang/test/Preprocessor/predefined-arch-macros.c +++ b/clang/test/Preprocessor/predefined-arch-macros.c @@ -1867,13 +1867,23 @@ // RUN: %clang -march=graniterapids-d -m32 -E -dM %s -o - 2>&1 \ // RUN: --target=i386 \ // RUN: | FileCheck -match-full-lines %s -check-prefixes=CHECK_GNR_M32,CHECK_GNRD_M32 +// RUN: %clang -march=diamondrapids -m32 -E -dM %s -o - 2>&1 \ +// RUN: --target=i386 \ +// RUN: | FileCheck -match-full-lines %s -check-prefixes=CHECK_GNR_M32,CHECK_GNRD_M32,CHECK_DMR_M32 // CHECK_GNR_M32: #define __AES__ 1 +// CHECK_DMR_M32: #define __AMX_AVX512__ 1 // CHECK_GNR_M32: #define __AMX_BF16__ 1 // CHECK_GNR_M32-NOT: #define __AMX_COMPLEX__ 1 // CHECK_GNRD_M32: #define __AMX_COMPLEX__ 1 // CHECK_GNR_M32: #define __AMX_FP16__ 1 +// CHECK_DMR_M32: #define __AMX_FP8__ 1 // CHECK_GNR_M32: #define __AMX_INT8__ 1 +// CHECK_DMR_M32: #define __AMX_MOVRS__ 1 +// CHECK_DMR_M32: #define __AMX_TF32__ 1 // CHECK_GNR_M32: #define __AMX_TILE__ 1 +// CHECK_DMR_M32: #define __AMX_TRANSPOSE__ 1 +// CHECK_DMR_M32: #define __AVX10_2_512__ 1 +// CHECK_DMR_M32: #define __AVX10_2__ 1 // CHECK_GNR_M32: #define __AVX2__ 1 // CHECK_GNR_M32: #define __AVX512BF16__ 1 // CHECK_GNR_M32: #define __AVX512BITALG__ 1 @@ -1888,13 +1898,21 @@ // CHECK_GNR_M32: #define __AVX512VL__ 1 // CHECK_GNR_M32: #define __AVX512VNNI__ 1 // CHECK_GNR_M32: #define __AVX512VPOPCNTDQ__ 1 +// CHECK_DMR_M32: #define __AVXIFMA__ 1 +// CHECK_DMR_M32: #define __AVXNECONVERT__ 1 +// CHECK_DMR_M32: #define __AVXVNNIINT16__ 1 +// CHECK_DMR_M32: #define __AVXVNNIINT8__ 1 // CHECK_GNR_M32: #define __AVXVNNI__ 1 // CHECK_GNR_M32: #define __AVX__ 1 // CHECK_GNR_M32: #define __BMI2__ 1 // CHECK_GNR_M32: #define __BMI__ 1 +// CHECK_DMR_M32: #define __CCMP__ 1 +// CHECK_DMR_M32: #define __CF__ 1 // CHECK_GNR_M32: #define __CLDEMOTE__ 1 // CHECK_GNR_M32: #define __CLFLUSHOPT__ 1 // CHECK_GNR_M32: #define __CLWB__ 1 +// CHECK_DMR_M32: #define __CMPCCXADD__ 1 +// CHECK_DMR_M32: #define __EGPR__ 1 // CHECK_GNR_M32: #define __ENQCMD__ 1 // CHECK_GNR_M32: #define __EVEX256__ 1 // CHECK_GNR_M32: #define __EVEX512__ 1 @@ -1905,20 +1923,28 @@ // CHECK_GNR_M32: #define __LZCNT__ 1 // CHECK_GNR_M32: #define __MMX__ 1 // CHECK_GNR_M32: #define __MOVBE__ 1 +// CHECK_DMR_M32: #define __MOVRS__ 1 +// CHECK_DMR_M32: #define __NDD__ 1 +// CHECK_DMR_M32: #define __NF__ 1 // CHECK_GNR_M32: #define __PCLMUL__ 1 // CHECK_GNR_M32: #define __PCONFIG__ 1 // CHECK_GNR_M32: #define __PKU__ 1 // CHECK_GNR_M32: #define __POPCNT__ 1 +// CHECK_DMR_M32: #define __PPX__ 1 // CHECK_GNR_M32: #define __PREFETCHI__ 1 // CHECK_GNR_M32: #define __PRFCHW__ 1 // CHECK_GNR_M32: #define __PTWRITE__ 1 +// CHECK_DMR_M32: #define __PUSH2POP2__ 1 // CHECK_GNR_M32: #define __RDPID__ 1 // CHECK_GNR_M32: #define __RDRND__ 1 // CHECK_GNR_M32: #define __RDSEED__ 1 // CHECK_GNR_M32: #define __SERIALIZE__ 1 // CHECK_GNR_M32: #define __SGX__ 1 +// CHECK_DMR_M32: #define __SHA512__ 1 // CHECK_GNR_M32: #define __SHA__ 1 // CHECK_GNR_M32: #define __SHSTK__ 1 +// CHECK_DMR_M32: #define __SM3__ 1 +// CHECK_DMR_M32: #define __SM4__ 1 // CHECK_GNR_M32: #define __SSE2__ 1 // CHECK_GNR_M32: #define __SSE3__ 1 // CHECK_GNR_M32: #define __SSE4_1__ 1 @@ -1935,6 +1961,7 @@ // CHECK_GNR_M32: #define __XSAVEOPT__ 1 // CHECK_GNR_M32: #define __XSAVES__ 1 // CHECK_GNR_M32: #define __XSAVE__ 1 +// CHECK_DMR_M32: #define __ZU__ 1 // CHECK_GNR_M32: #define __corei7 1 // CHECK_GNR_M32: #define __corei7__ 1 // CHECK_GNR_M32: #define __i386 1 @@ -1948,13 +1975,23 @@ // RUN: %clang -march=graniterapids-d -m64 -E -dM %s -o - 2>&1 \ // RUN: --target=x86_64 \ // RUN: | FileCheck -match-full-lines %s -check-prefixes=CHECK_GNR_M64,CHECK_GNRD_M64 +// RUN: %clang -march=diamondrapids -m64 -E -dM %s -o - 2>&1 \ +// RUN: --target=x86_64 \ +// RUN: | FileCheck -match-full-lines %s -check-prefixes=CHECK_GNR_M64,CHECK_GNRD_M64,CHECK_DMR_M64 // CHECK_GNR_M64: #define __AES__ 1 +// CHECK_DMR_M64: #define __AMX_AVX512__ 1 // CHECK_GNR_M64: #define __AMX_BF16__ 1 // CHECK_GNR_M64-NOT: #define __AMX_COMPLEX__ 1 // CHECK_GNRD_M64: #define __AMX_COMPLEX__ 1 // CHECK_GNR_M64: #define __AMX_FP16__ 1 +// CHECK_DMR_M64: #define __AMX_FP8__ 1 // CHECK_GNR_M64: #define __AMX_INT8__ 1 +// CHECK_DMR_M64: #define __AMX_MOVRS__ 1 +// CHECK_DMR_M64: #define __AMX_TF32__ 1 // CHECK_GNR_M64: #define __AMX_TILE__ 1 +// CHECK_DMR_M64: #define __AMX_TRANSPOSE__ 1 +// CHECK_DMR_M64: #define __AVX10_2_512__ 1 +// CHECK_DMR_M64: #define __AVX10_2__ 1 // CHECK_GNR_M64: #define __AVX2__ 1 // CHECK_GNR_M64: #define __AVX512BF16__ 1 // CHECK_GNR_M64: #define __AVX512BITALG__ 1 @@ -1969,13 +2006,21 @@ // CHECK_GNR_M64: #define __AVX512VL__ 1 // CHECK_GNR_M64: #define __AVX512VNNI__ 1 // CHECK_GNR_M64: #define __AVX512VPOPCNTDQ__ 1 +// CHECK_DMR_M64: #define __AVXIFMA__ 1 +// CHECK_DMR_M64: #define __AVXNECONVERT__ 1 +// CHECK_DMR_M64: #define __AVXVNNIINT16__ 1 +// CHECK_DMR_M64: #define __AVXVNNIINT8__ 1 // CHECK_GNR_M64: #define __AVXVNNI__ 1 // CHECK_GNR_M64: #define __AVX__ 1 // CHECK_GNR_M64: #define __BMI2__ 1 // CHECK_GNR_M64: #define __BMI__ 1 +// CHECK_DMR_M64: #define __CCMP__ 1 +// CHECK_DMR_M64: #define __CF__ 1 // CHECK_GNR_M64: #define __CLDEMOTE__ 1 // CHECK_GNR_M64: #define __CLFLUSHOPT__ 1 // CHECK_GNR_M64: #define __CLWB__ 1 +// CHECK_DMR_M64: #define __CMPCCXADD__ 1 +// CHECK_DMR_M64: #define __EGPR__ 1 // CHECK_GNR_M64: #define __ENQCMD__ 1 // CHECK_GNR_M64: #define __EVEX256__ 1 // CHECK_GNR_M64: #define __EVEX512__ 1 @@ -1986,20 +2031,28 @@ // CHECK_GNR_M64: #define __LZCNT__ 1 // CHECK_GNR_M64: #define __MMX__ 1 // CHECK_GNR_M64: #define __MOVBE__ 1 +// CHECK_DMR_M64: #define __MOVRS__ 1 +// CHECK_DMR_M64: #define __NDD__ 1 +// CHECK_DMR_M64: #define __NF__ 1 // CHECK_GNR_M64: #define __PCLMUL__ 1 // CHECK_GNR_M64: #define __PCONFIG__ 1 // CHECK_GNR_M64: #define __PKU__ 1 // CHECK_GNR_M64: #define __POPCNT__ 1 +// CHECK_DMR_M64: #define __PPX__ 1 // CHECK_GNR_M64: #define __PREFETCHI__ 1 // CHECK_GNR_M64: #define __PRFCHW__ 1 // CHECK_GNR_M64: #define __PTWRITE__ 1 +// CHECK_DMR_M64: #define __PUSH2POP2__ 1 // CHECK_GNR_M64: #define __RDPID__ 1 // CHECK_GNR_M64: #define __RDRND__ 1 // CHECK_GNR_M64: #define __RDSEED__ 1 // CHECK_GNR_M64: #define __SERIALIZE__ 1 // CHECK_GNR_M64: #define __SGX__ 1 +// CHECK_DMR_M64: #define __SHA512__ 1 // CHECK_GNR_M64: #define __SHA__ 1 // CHECK_GNR_M64: #define __SHSTK__ 1 +// CHECK_DMR_M64: #define __SM3__ 1 +// CHECK_DMR_M64: #define __SM4__ 1 // CHECK_GNR_M64: #define __SSE2__ 1 // CHECK_GNR_M64: #define __SSE3__ 1 // CHECK_GNR_M64: #define __SSE4_1__ 1 @@ -2016,6 +2069,7 @@ // CHECK_GNR_M64: #define __XSAVEOPT__ 1 // CHECK_GNR_M64: #define __XSAVES__ 1 // CHECK_GNR_M64: #define __XSAVE__ 1 +// CHECK_DMR_M64: #define __ZU__ 1 // CHECK_GNR_M64: #define __amd64 1 // CHECK_GNR_M64: #define __amd64__ 1 // CHECK_GNR_M64: #define __corei7 1 diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c index 2a3edc23f475326b043f7293a0ddf8d0c8a1a737..a440791d6cc6950e49421a13781ed08d98fabfb2 100644 --- a/clang/test/Preprocessor/ptrauth_feature.c +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -2,34 +2,37 @@ //// For example, -fptrauth-init-fini will not affect codegen without -fptrauth-calls, but the preprocessor feature would be set anyway. // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-intrinsics | \ -// RUN: FileCheck %s --check-prefixes=INTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=INTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-calls | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,CALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,CALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-returns | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,RETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,RETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-vtable-pointer-address-discrimination | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,VPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-vtable-pointer-type-discrimination | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-type-info-vtable-pointer-discrimination | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,TYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,TYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-function-pointer-type-discrimination | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,FUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,FUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-init-fini | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,INITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,INITFINI,NOINITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-init-fini-address-discrimination | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,INITFINI_ADDR_DISCR,NOGOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,INITFINI_ADDR_DISCR,NOGOTOS,NOELFGOT // RUN: %clang_cc1 -E %s -triple=aarch64 -fptrauth-indirect-gotos | \ -// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,GOTOS +// RUN: FileCheck %s --check-prefixes=NOINTRIN,NOCALLS,NORETS,NOVPTR_ADDR_DISCR,NOVPTR_TYPE_DISCR,NOTYPE_INFO_DISCR,NOFUNC,NOINITFINI,NOINITFINI_ADDR_DISCR,GOTOS,NOELFGOT + +// 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) // INTRIN: has_ptrauth_intrinsics @@ -119,3 +122,11 @@ void has_ptrauth_indirect_gotos() {} // NOGOTOS: no_ptrauth_indirect_gotos void no_ptrauth_indirect_gotos() {} #endif + +#if __has_feature(ptrauth_elf_got) +// ELFGOT: has_ptrauth_elf_got +void has_ptrauth_elf_got() {} +#else +// NOELFGOT: no_ptrauth_elf_got +void no_ptrauth_elf_got() {} +#endif diff --git a/clang/test/Refactor/Extract/ObjCProperty.m b/clang/test/Refactor/Extract/ObjCProperty.m index 152ccb3484215641b14a1678daf6cf20fca2eadf..23c9a8941b7ab93d16ef6a0d1af87117570a6e9b 100644 --- a/clang/test/Refactor/Extract/ObjCProperty.m +++ b/clang/test/Refactor/Extract/ObjCProperty.m @@ -36,6 +36,6 @@ /*range prohibit_setter=->+0:55*/self.implicitSetter = 0; } // CHECK: 2 'prohibit_setter' results: -// CHECK: the selected expression can't be extracted +// CHECK: the selected expression cannot be extracted @end diff --git a/clang/test/Sema/Inputs/lifetime-analysis.h b/clang/test/Sema/Inputs/lifetime-analysis.h new file mode 100644 index 0000000000000000000000000000000000000000..41d1e2f074cc83dbd6fa5340545b006fbfa926d8 --- /dev/null +++ b/clang/test/Sema/Inputs/lifetime-analysis.h @@ -0,0 +1,138 @@ + +namespace __gnu_cxx { +template +struct basic_iterator { + basic_iterator operator++(); + T& operator*() const; + T* operator->() const; +}; + +template +bool operator!=(basic_iterator, basic_iterator); +} + +namespace std { +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template +typename remove_reference::type &&move(T &&t) noexcept; + +template +auto data(const C &c) -> decltype(c.data()); + +template +auto begin(C &c) -> decltype(c.begin()); + +template +T *begin(T (&array)[N]); + +using size_t = decltype(sizeof(0)); + +template +struct initializer_list { + const T* ptr; size_t sz; +}; +template class allocator {}; +template > +struct vector { + typedef __gnu_cxx::basic_iterator iterator; + iterator begin(); + iterator end(); + const T *data() const; + vector(); + vector(initializer_list __l, + const Alloc& alloc = Alloc()); + + template + vector(InputIterator first, InputIterator __last); + + T &at(int n); +}; + +template +struct basic_string_view { + basic_string_view(); + basic_string_view(const T *); + const T *begin() const; +}; +using string_view = basic_string_view; + +template struct iter { + iter& operator-=(int); + + iter operator-(int _Off) const { + iter _Tmp = *this; + return _Tmp -= _Off; + } +}; + +template +struct basic_string { + basic_string(); + basic_string(const T *); + const T *c_str() const; + operator basic_string_view () const; + using const_iterator = iter; +}; +using string = basic_string; + +template +struct unique_ptr { + T &operator*(); + T *get() const; +}; + +template +struct optional { + optional(); + optional(const T&); + + template + optional(U&& t); + + template + optional(optional&& __t); + + T &operator*() &; + T &&operator*() &&; + T &value() &; + T &&value() &&; +}; +template +optional<__decay(T)> make_optional(T&&); + + +template +struct stack { + T &top(); +}; + +struct any {}; + +template +T any_cast(const any& operand); + +template +struct reference_wrapper { + template + reference_wrapper(U &&); +}; + +template +reference_wrapper ref(T& t) noexcept; + +struct false_type { + static constexpr bool value = false; + constexpr operator bool() const noexcept { return value; } +}; +struct true_type { + static constexpr bool value = true; + constexpr operator bool() const noexcept { return value; } +}; + +template struct is_pointer : false_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +} diff --git a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp index 795bb760533034207cfb569cc05f5200d2bac3c3..93d4b0070169378e6b4fdc032ca361ba50255f73 100644 --- a/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp +++ b/clang/test/Sema/aarch64-sve2-intrinsics/acle_sve2_aes_bitperm_sha3_sm4.cpp @@ -14,17 +14,17 @@ void test(uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64) { - // expected-error@+2 {{'svaesd_u8' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svaesd' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svaesd_u8' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svaesd' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svaesd,_u8,,)(svundef_u8(), svundef_u8()); - // expected-error@+2 {{'svaese_u8' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svaese' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svaese_u8' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svaese' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svaese,_u8,,)(svundef_u8(), svundef_u8()); - // expected-error@+2 {{'svaesimc_u8' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svaesimc' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svaesimc_u8' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svaesimc' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svaesimc,_u8,,)(svundef_u8()); - // expected-error@+2 {{'svaesmc_u8' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svaesmc' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svaesmc_u8' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svaesmc' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svaesmc,_u8,,)(svundef_u8()); // expected-error@+2 {{'svbdep_u8' needs target feature sve,sve2-bitperm}} // overload-error@+1 {{'svbdep' needs target feature sve,sve2-bitperm}} @@ -107,17 +107,17 @@ void test(uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64) // expected-error@+2 {{'svbgrp_n_u64' needs target feature sve,sve2-bitperm}} // overload-error@+1 {{'svbgrp' needs target feature sve,sve2-bitperm}} SVE_ACLE_FUNC(svbgrp,_n_u64,,)(svundef_u64(), u64); - // expected-error@+2 {{'svpmullb_pair_u64' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svpmullb_pair' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svpmullb_pair_u64' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svpmullb_pair' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svpmullb_pair,_u64,,)(svundef_u64(), svundef_u64()); - // expected-error@+2 {{'svpmullb_pair_n_u64' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svpmullb_pair' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svpmullb_pair_n_u64' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svpmullb_pair' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svpmullb_pair,_n_u64,,)(svundef_u64(), u64); - // expected-error@+2 {{'svpmullt_pair_u64' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svpmullt_pair' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svpmullt_pair_u64' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svpmullt_pair' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svpmullt_pair,_u64,,)(svundef_u64(), svundef_u64()); - // expected-error@+2 {{'svpmullt_pair_n_u64' needs target feature sve,sve2-aes}} - // overload-error@+1 {{'svpmullt_pair' needs target feature sve,sve2-aes}} + // expected-error@+2 {{'svpmullt_pair_n_u64' needs target feature sve,sve2,sve-aes}} + // overload-error@+1 {{'svpmullt_pair' needs target feature sve,sve2,sve-aes}} SVE_ACLE_FUNC(svpmullt_pair,_n_u64,,)(svundef_u64(), u64); // expected-error@+2 {{'svrax1_u64' needs target feature sve,sve2-sha3}} // overload-error@+1 {{'svrax1' needs target feature sve,sve2-sha3}} diff --git a/clang/test/Sema/amdgcn-address-spaces.c b/clang/test/Sema/amdgcn-address-spaces.c new file mode 100644 index 0000000000000000000000000000000000000000..50c12993ac69b8b17c6f6f9c9b04c65dbbd33c3d --- /dev/null +++ b/clang/test/Sema/amdgcn-address-spaces.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 %s -triple amdgcn-amd-amdhsa -fsyntax-only -verify + +#define _AS0 __attribute__((address_space(0))) +#define _AS1 __attribute__((address_space(1))) +#define _AS2 __attribute__((address_space(2))) +#define _AS3 __attribute__((address_space(3))) +#define _AS4 __attribute__((address_space(4))) +#define _AS5 __attribute__((address_space(5))) +#define _AS999 __attribute__((address_space(999))) + +void *p1(void _AS1 *p) { return p; } +void *p2(void _AS2 *p) { return p; } +void *p3(void _AS3 *p) { return p; } +void *p4(void _AS4 *p) { return p; } +void *p5(void _AS5 *p) { return p; } +void *pi(void _AS999 *p) { return p; } // expected-error {{returning '_AS999 void *' from a function with result type 'void *' changes address space of pointer}} +void *pc(void __attribute__((opencl_local)) *p) { return p; } // expected-error {{returning '__local void *' from a function with result type 'void *' changes address space of pointer}} +void _AS1 *r0(void _AS1 *p) { return p; } +void _AS1 *r1(void *p) { return p; } // expected-error {{returning 'void *' from a function with result type '_AS1 void *' changes address space of pointer}} +void _AS1 *r2(void *p) { return (void _AS1 *)p; } diff --git a/clang/test/Sema/arm-mfp8.c b/clang/test/Sema/arm-mfp8.c index e917078f50ed7e5296e6eae34e4bf67e1bd24348..9ddc07c3a07979c1ab6fcf49c8c9a2e56e4c0b3c 100644 --- a/clang/test/Sema/arm-mfp8.c +++ b/clang/test/Sema/arm-mfp8.c @@ -1,11 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-arm-none-eabi -target-feature -fp8 %s // REQUIRES: aarch64-registered-target -#include __mfp8 test_cast_from_float(unsigned in) { - return (__mfp8)in; // expected-error {{used type '__mfp8' (aka '__MFloat8_t') where arithmetic or pointer type is required}} + return (__mfp8)in; // expected-error {{used type '__mfp8' where arithmetic or pointer type is required}} } unsigned test_cast_to_int(__mfp8 in) { - return (unsigned)in; // expected-error {{operand of type '__mfp8' (aka '__MFloat8_t') where arithmetic or pointer type is required}} + return (unsigned)in; // expected-error {{operand of type '__mfp8' where arithmetic or pointer type is required}} } diff --git a/clang/test/Sema/arm-mfp8.cpp b/clang/test/Sema/arm-mfp8.cpp index e882c382522c22355bac7eda668d5f63f6b01994..be5bc9bb71dbd236632d545d45f492703112d7a2 100644 --- a/clang/test/Sema/arm-mfp8.cpp +++ b/clang/test/Sema/arm-mfp8.cpp @@ -3,6 +3,39 @@ // REQUIRES: aarch64-registered-target +__mfp8 test_static_cast_from_char(char in) { + return static_cast<__mfp8>(in); // scalar-error {{static_cast from 'char' to '__mfp8' is not allowed}} +} + +char test_static_cast_to_char(__mfp8 in) { + return static_cast(in); // scalar-error {{static_cast from '__mfp8' to 'char' is not allowed}} +} + +void test(bool b) { + __mfp8 mfp8; + + mfp8 + mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}} + mfp8 - mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}} + mfp8 * mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}} + mfp8 / mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' and '__mfp8')}} + ++mfp8; // scalar-error {{cannot increment value of type '__mfp8'}} + --mfp8; // scalar-error {{cannot decrement value of type '__mfp8'}} + + char u8; + + mfp8 + u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}} + u8 + mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}} + mfp8 - u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}} + u8 - mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}} + mfp8 * u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}} + u8 * mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}} + mfp8 / u8; // scalar-error {{invalid operands to binary expression ('__mfp8' and 'char')}} + u8 / mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8')}} + mfp8 = u8; // scalar-error {{assigning to '__mfp8' from incompatible type 'char'}} + u8 = mfp8; // scalar-error {{assigning to 'char' from incompatible type '__mfp8'}} + mfp8 + (b ? u8 : mfp8); // scalar-error {{incompatible operand types ('char' and '__mfp8')}} +} + #include void test_vector_sve(svmfloat8_t a, svuint8_t c) { a + c; // sve-error {{cannot convert between vector type 'svuint8_t' (aka '__SVUint8_t') and vector type 'svmfloat8_t' (aka '__SVMfloat8_t') as implicit conversion would cause truncation}} @@ -29,35 +62,3 @@ void test_vector(mfloat8x8_t a, mfloat8x16_t b, uint8x8_t c) { c * b; // neon-error {{cannot convert between vector and non-scalar values ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x16_t' (aka '__MFloat8x16_t'))}} c / b; // neon-error {{cannot convert between vector and non-scalar values ('uint8x8_t' (vector of 8 'uint8_t' values) and 'mfloat8x16_t' (aka '__MFloat8x16_t'))}} } -__mfp8 test_static_cast_from_char(char in) { - return static_cast<__mfp8>(in); // scalar-error {{static_cast from 'char' to '__mfp8' (aka '__MFloat8_t') is not allowed}} -} - -char test_static_cast_to_char(__mfp8 in) { - return static_cast(in); // scalar-error {{static_cast from '__mfp8' (aka '__MFloat8_t') to 'char' is not allowed}} -} -void test(bool b) { - __mfp8 mfp8; - - mfp8 + mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}} - mfp8 - mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}} - mfp8 * mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}} - mfp8 / mfp8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and '__mfp8')}} - ++mfp8; // scalar-error {{cannot increment value of type '__mfp8' (aka '__MFloat8_t')}} - --mfp8; // scalar-error {{cannot decrement value of type '__mfp8' (aka '__MFloat8_t')}} - - char u8; - - mfp8 + u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}} - u8 + mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}} - mfp8 - u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}} - u8 - mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}} - mfp8 * u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}} - u8 * mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}} - mfp8 / u8; // scalar-error {{invalid operands to binary expression ('__mfp8' (aka '__MFloat8_t') and 'char')}} - u8 / mfp8; // scalar-error {{invalid operands to binary expression ('char' and '__mfp8' (aka '__MFloat8_t'))}} - mfp8 = u8; // scalar-error {{assigning to '__mfp8' (aka '__MFloat8_t') from incompatible type 'char'}} - u8 = mfp8; // scalar-error {{assigning to 'char' from incompatible type '__mfp8' (aka '__MFloat8_t')}} - mfp8 + (b ? u8 : mfp8); // scalar-error {{incompatible operand types ('char' and '__mfp8' (aka '__MFloat8_t'))}} -} - diff --git a/clang/test/Sema/asm.c b/clang/test/Sema/asm.c index 28ef3ec6ce09c2a6bee95b7b3654f13e9ccc35a7..a9cff5947ef5d00407e61b4cd1635d667e2918bd 100644 --- a/clang/test/Sema/asm.c +++ b/clang/test/Sema/asm.c @@ -90,7 +90,7 @@ int test7(unsigned long long b) { // PR3904 void test8(int i) { - // A number in an input constraint can't point to a read-write constraint. + // A number in an input constraint cannot point to a read-write constraint. asm("" : "+r" (i), "=r"(i) : "0" (i)); // expected-error{{invalid input constraint '0' in asm}} } @@ -359,7 +359,7 @@ void test19(long long x) asm ("" : "=rm" (x): "0" (a)); // expected-error {{unsupported inline asm: input with type 'st_size64' (aka 'struct _st_size64') matching output with type 'long long'}} // FIXME: This case is actually supported by codegen. asm ("" : "=rm" (a): "0" (d)); // expected-error {{unsupported inline asm: input with type 'st_size32' (aka 'struct _st_size32') matching output with type 'st_size64' (aka 'struct _st_size64')}} - asm ("" : "=rm" (b): "0" (1)); // expected-error {{impossible constraint in asm: can't store value into a register}} + asm ("" : "=rm" (b): "0" (1)); // expected-error {{impossible constraint in asm: cannot store value into a register}} // FIXME: This case should be supported by codegen, but it fails now. asm ("" : "=rm" (e): "0" (1)); // no-error // FIXME: This case should be supported by codegen, but it fails now. diff --git a/clang/test/Sema/attr-nonblocking-constraints.cpp b/clang/test/Sema/attr-nonblocking-constraints.cpp index cc9108c0a4fbd662bf894898b87d426fd843ea1f..bbc909f627f4c3b2ab584c72e6329f6ae7a6f842 100644 --- a/clang/test/Sema/attr-nonblocking-constraints.cpp +++ b/clang/test/Sema/attr-nonblocking-constraints.cpp @@ -144,6 +144,41 @@ void nb9() [[clang::nonblocking]] expected-note {{in template expansion here}} } +// Make sure we verify lambdas produced from template expansions. +struct HasTemplatedLambda { + void (*fptr)() [[clang::nonblocking]]; + + template + HasTemplatedLambda(const C&) + : fptr{ []() [[clang::nonblocking]] { + auto* y = new int; // expected-warning {{lambda with 'nonblocking' attribute must not allocate or deallocate memory}} + } } + {} +}; + +void nb9a() +{ + HasTemplatedLambda bad(42); +} + +// Templated function and lambda. +template +void TemplatedFunc(T x) [[clang::nonblocking]] { + auto* ptr = new T; // expected-warning {{function with 'nonblocking' attribute must not allocate or deallocate memory}} +} + +void nb9b() [[clang::nonblocking]] { + TemplatedFunc(42); // expected-note {{in template expansion here}} + + auto foo = [](auto x) [[clang::nonblocking]] { + auto* ptr = new int; // expected-warning {{lambda with 'nonblocking' attribute must not allocate or deallocate memory}} + return x; + }; + + // Note that foo() won't be validated unless instantiated. + foo(42); +} + void nb10( void (*fp1)(), // expected-note {{function pointer cannot be inferred 'nonblocking'}} void (*fp2)() [[clang::nonblocking]] diff --git a/clang/test/Sema/c2x-nodiscard.c b/clang/test/Sema/c2x-nodiscard.c index f8b0567366465df2b186e5c37cde7d38f8918f01..e2537bcf1d29d6dd97545464dff3ccd34cda1ea7 100644 --- a/clang/test/Sema/c2x-nodiscard.c +++ b/clang/test/Sema/c2x-nodiscard.c @@ -31,10 +31,10 @@ enum E2 get_e(void); [[nodiscard]] int get_i(void); void f2(void) { - get_s(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - get_s3(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute: Wrong}} + get_s(); // expected-warning {{ignoring return value of type 'S4' declared with 'nodiscard' attribute}} + get_s3(); // expected-warning {{ignoring return value of type 'S3' declared with 'nodiscard' attribute: Wrong}} get_i(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - get_e(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + get_e(); // expected-warning {{ignoring return value of type 'E2' declared with 'nodiscard' attribute}} // Okay, warnings are not encouraged (void)get_s(); @@ -50,7 +50,7 @@ struct [[nodiscard]] error_info{ struct error_info enable_missile_safety_mode(void); void launch_missiles(void); void test_missiles(void) { - enable_missile_safety_mode(); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} + enable_missile_safety_mode(); // expected-warning {{ignoring return value of type 'error_info' declared with 'nodiscard'}} launch_missiles(); } diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp index c6b1b37cef28b4367f372355d4b5e060a5594ba0..7063c290479f6cac47feac5f5f2711a25c9b91ef 100644 --- a/clang/test/Sema/constant_builtins_vector.cpp +++ b/clang/test/Sema/constant_builtins_vector.cpp @@ -19,6 +19,8 @@ typedef double vector4double __attribute__((__vector_size__(32))); typedef float vector4float __attribute__((__vector_size__(16))); typedef long long vector4long __attribute__((__vector_size__(32))); typedef int vector4int __attribute__((__vector_size__(16))); +typedef unsigned long long vector4ulong __attribute__((__vector_size__(32))); +typedef unsigned int vector4uint __attribute__((__vector_size__(16))); typedef short vector4short __attribute__((__vector_size__(8))); typedef char vector4char __attribute__((__vector_size__(4))); typedef BitInt8 vector4BitInt8 __attribute__((__vector_size__(4))); @@ -723,3 +725,55 @@ not within the bounds of the input vectors; index of -1 found at position 0 is n permitted in a constexpr context}} vector4charConst1, vector4charConst2, -1, -1, -1, -1); + +static_assert(__builtin_reduce_add((vector4char){}) == 0); +static_assert(__builtin_reduce_add((vector4char){1, 2, 3, 4}) == 10); +static_assert(__builtin_reduce_add((vector4short){10, 20, 30, 40}) == 100); +static_assert(__builtin_reduce_add((vector4int){100, 200, 300, 400}) == 1000); +static_assert(__builtin_reduce_add((vector4long){1000, 2000, 3000, 4000}) == 10000); +constexpr int reduceAddInt1 = __builtin_reduce_add((vector4int){~(1 << 31), 0, 0, 1}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'int'}} +constexpr long long reduceAddLong1 = __builtin_reduce_add((vector4long){~(1LL << 63), 0, 0, 1}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'long long'}} +constexpr int reduceAddInt2 = __builtin_reduce_add((vector4int){(1 << 31), 0, 0, -1}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'int'}} +constexpr long long reduceAddLong2 = __builtin_reduce_add((vector4long){(1LL << 63), 0, 0, -1}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'long long'}} +static_assert(__builtin_reduce_add((vector4uint){~0U, 0, 0, 1}) == 0); +static_assert(__builtin_reduce_add((vector4ulong){~0ULL, 0, 0, 1}) == 0); + +static_assert(__builtin_reduce_mul((vector4char){}) == 0); +static_assert(__builtin_reduce_mul((vector4char){1, 2, 3, 4}) == 24); +static_assert(__builtin_reduce_mul((vector4short){1, 2, 30, 40}) == 2400); +static_assert(__builtin_reduce_mul((vector4int){10, 20, 300, 400}) == 24000000); +static_assert(__builtin_reduce_mul((vector4long){1000L, 2000L, 3000L, 4000L}) == 24000000000000L); +constexpr int reduceMulInt1 = __builtin_reduce_mul((vector4int){~(1 << 31), 1, 1, 2}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'int'}} +constexpr long long reduceMulLong1 = __builtin_reduce_mul((vector4long){~(1LL << 63), 1, 1, 2}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'long long'}} +constexpr int reduceMulInt2 = __builtin_reduce_mul((vector4int){(1 << 31), 1, 1, 2}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'int'}} +constexpr long long reduceMulLong2 = __builtin_reduce_mul((vector4long){(1LL << 63), 1, 1, 2}); +// expected-error@-1 {{must be initialized by a constant expression}} \ +// expected-note@-1 {{outside the range of representable values of type 'long long'}} +static_assert(__builtin_reduce_mul((vector4uint){~0U, 1, 1, 2}) == ~0U - 1); +static_assert(__builtin_reduce_mul((vector4ulong){~0ULL, 1, 1, 2}) == ~0ULL - 1); + +static_assert(__builtin_reduce_and((vector4char){}) == 0); +static_assert(__builtin_reduce_and((vector4char){(char)0x11, (char)0x22, (char)0x44, (char)0x88}) == 0); +static_assert(__builtin_reduce_and((vector4short){(short)0x1111, (short)0x2222, (short)0x4444, (short)0x8888}) == 0); +static_assert(__builtin_reduce_and((vector4int){(int)0x11111111, (int)0x22222222, (int)0x44444444, (int)0x88888888}) == 0); +static_assert(__builtin_reduce_and((vector4long){(long long)0x1111111111111111L, (long long)0x2222222222222222L, (long long)0x4444444444444444L, (long long)0x8888888888888888L}) == 0L); +static_assert(__builtin_reduce_and((vector4char){(char)-1, (char)~0x22, (char)~0x44, (char)~0x88}) == 0x11); +static_assert(__builtin_reduce_and((vector4short){(short)~0x1111, (short)-1, (short)~0x4444, (short)~0x8888}) == 0x2222); +static_assert(__builtin_reduce_and((vector4int){(int)~0x11111111, (int)~0x22222222, (int)-1, (int)~0x88888888}) == 0x44444444); +static_assert(__builtin_reduce_and((vector4long){(long long)~0x1111111111111111L, (long long)~0x2222222222222222L, (long long)~0x4444444444444444L, (long long)-1}) == 0x8888888888888888L); +static_assert(__builtin_reduce_and((vector4uint){0x11111111U, 0x22222222U, 0x44444444U, 0x88888888U}) == 0U); +static_assert(__builtin_reduce_and((vector4ulong){0x1111111111111111UL, 0x2222222222222222UL, 0x4444444444444444UL, 0x8888888888888888UL}) == 0L); diff --git a/clang/test/Sema/nvptx-address-spaces.c b/clang/test/Sema/nvptx-address-spaces.c new file mode 100644 index 0000000000000000000000000000000000000000..184feef9612e57e4729e8415f6570b21beb65e41 --- /dev/null +++ b/clang/test/Sema/nvptx-address-spaces.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 %s -triple nvptx64-nvidia-cuda -fsyntax-only -verify + +#define _AS0 __attribute__((address_space(0))) +#define _AS1 __attribute__((address_space(1))) +#define _AS2 __attribute__((address_space(2))) +#define _AS3 __attribute__((address_space(3))) +#define _AS4 __attribute__((address_space(4))) +#define _AS5 __attribute__((address_space(5))) +#define _AS999 __attribute__((address_space(999))) + +void *p1(void _AS1 *p) { return p; } +void *p2(void _AS2 *p) { return p; } // expected-error {{returning '_AS2 void *' from a function with result type 'void *' changes address space of pointer}} +void *p3(void _AS3 *p) { return p; } +void *p4(void _AS4 *p) { return p; } +void *p5(void _AS5 *p) { return p; } +void *pi(void _AS999 *p) { return p; } // expected-error {{returning '_AS999 void *' from a function with result type 'void *' changes address space of pointer}} +void *pc(void __attribute__((opencl_local)) *p) { return p; } // expected-error {{returning '__local void *' from a function with result type 'void *' changes address space of pointer}} +void _AS1 *r0(void _AS1 *p) { return p; } +void _AS1 *r1(void *p) { return p; } // expected-error {{returning 'void *' from a function with result type '_AS1 void *' changes address space of pointer}} +void _AS1 *r2(void *p) { return (void _AS1 *)p; } + diff --git a/clang/test/Sema/pragma-attribute-strict-subjects.c b/clang/test/Sema/pragma-attribute-strict-subjects.c index 4f37c271ce34a4506c6d22170648fa34243c01b2..85b484799529a161adf80e0d8ba04a0a2f66a67a 100644 --- a/clang/test/Sema/pragma-attribute-strict-subjects.c +++ b/clang/test/Sema/pragma-attribute-strict-subjects.c @@ -52,16 +52,16 @@ #pragma clang attribute pop #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), variable, enum)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} #pragma clang attribute pop #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(enum_constant, function, record(unless(is_union)), variable, variable(is_parameter), enum)) // FIXME: comma in this diagnostic is wrong. -// expected-error@-2 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} +// expected-error@-2 {{attribute 'abi_tag' cannot be applied to 'enum_constant', and 'enum'}} #pragma clang attribute pop #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(function, record(unless(is_union)), enum)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} #pragma clang attribute pop // Verify the non-strict subject set verification. @@ -96,12 +96,12 @@ #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = any(record(unless(is_union)), function, variable, enum, enum_constant)) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum_constant', and 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum_constant', and 'enum'}} #pragma clang attribute pop #pragma clang attribute push (__attribute__((abi_tag("a"))), apply_to = enum) -// expected-error@-1 {{attribute 'abi_tag' can't be applied to 'enum'}} +// expected-error@-1 {{attribute 'abi_tag' cannot be applied to 'enum'}} #pragma clang attribute pop @@ -124,21 +124,21 @@ #pragma clang attribute pop #pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_interface, objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +// expected-error@-1 {{attribute 'objc_subclassing_restricted' cannot be applied to 'objc_protocol'}} #pragma clang attribute pop #pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +// expected-error@-1 {{attribute 'objc_subclassing_restricted' cannot be applied to 'objc_protocol'}} // Don't report an error about missing 'objc_interface' as we aren't parsing // Objective-C. #pragma clang attribute pop #pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_interface, objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +// expected-error@-1 {{attribute 'objc_subclassing_restricted' cannot be applied to 'objc_protocol'}} #pragma clang attribute pop #pragma clang attribute push(__attribute__((objc_subclassing_restricted)), apply_to = any(objc_protocol)) -// expected-error@-1 {{attribute 'objc_subclassing_restricted' can't be applied to 'objc_protocol'}} +// expected-error@-1 {{attribute 'objc_subclassing_restricted' cannot be applied to 'objc_protocol'}} // Don't report an error about missing 'objc_interface' as we aren't parsing // Objective-C. #pragma clang attribute pop diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3fde386b8616c8fe3fbcad222689da9d37749f8 --- /dev/null +++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp @@ -0,0 +1,368 @@ +// RUN: %clang_cc1 --std=c++20 -fsyntax-only -verify -Wdangling-capture %s + +#include "Inputs/lifetime-analysis.h" + +// **************************************************************************** +// Capture an integer +// **************************************************************************** +namespace capture_int { +struct X {} x; +void captureInt(const int &i [[clang::lifetime_capture_by(x)]], X &x); +void captureRValInt(int &&i [[clang::lifetime_capture_by(x)]], X &x); +void noCaptureInt(int i [[clang::lifetime_capture_by(x)]], X &x); + +void use() { + int local; + captureInt(1, // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + x); + captureRValInt(1, x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureInt(local, x); + noCaptureInt(1, x); + noCaptureInt(local, x); +} +} // namespace capture_int + +// **************************************************************************** +// Capture std::string (gsl owner types) +// **************************************************************************** +namespace capture_string { +struct X {} x; +void captureString(const std::string &s [[clang::lifetime_capture_by(x)]], X &x); +void captureRValString(std::string &&s [[clang::lifetime_capture_by(x)]], X &x); + +void use() { + std::string local_string; + captureString(std::string(), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureString(local_string, x); + captureRValString(std::move(local_string), x); + captureRValString(std::string(), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} +} +} // namespace capture_string + +// **************************************************************************** +// Capture std::string_view (gsl pointer types) +// **************************************************************************** +namespace capture_string_view { +struct X {} x; +void captureStringView(std::string_view s [[clang::lifetime_capture_by(x)]], X &x); +void captureRValStringView(std::string_view &&sv [[clang::lifetime_capture_by(x)]], X &x); +void noCaptureStringView(std::string_view sv, X &x); + +std::string_view getLifetimeBoundView(const std::string& s [[clang::lifetimebound]]); +std::string_view getNotLifetimeBoundView(const std::string& s); +const std::string& getLifetimeBoundString(const std::string &s [[clang::lifetimebound]]); +const std::string& getLifetimeBoundString(std::string_view sv [[clang::lifetimebound]]); + +void use() { + std::string_view local_string_view; + std::string local_string; + captureStringView(local_string_view, x); + captureStringView(std::string(), // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + x); + + captureStringView(getLifetimeBoundView(local_string), x); + captureStringView(getNotLifetimeBoundView(std::string()), x); + captureRValStringView(std::move(local_string_view), x); + captureRValStringView(std::string(), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureRValStringView(std::string_view{"abcd"}, x); + + noCaptureStringView(local_string_view, x); + noCaptureStringView(std::string(), x); + + // With lifetimebound functions. + captureStringView(getLifetimeBoundView( + std::string() // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + ), x); + captureRValStringView(getLifetimeBoundView(local_string), x); + captureRValStringView(getLifetimeBoundView(std::string()), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureRValStringView(getNotLifetimeBoundView(std::string()), x); + noCaptureStringView(getLifetimeBoundView(std::string()), x); + captureStringView(getLifetimeBoundString(std::string()), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureStringView(getLifetimeBoundString(getLifetimeBoundView(std::string())), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureStringView(getLifetimeBoundString(getLifetimeBoundString( + std::string() // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + )), x); +} +} // namespace capture_string_view + +// **************************************************************************** +// Capture pointer (eg: std::string*) +// **************************************************************************** +const std::string* getLifetimeBoundPointer(const std::string &s [[clang::lifetimebound]]); +const std::string* getNotLifetimeBoundPointer(const std::string &s); + +namespace capture_pointer { +struct X {} x; +void capturePointer(const std::string* sp [[clang::lifetime_capture_by(x)]], X &x); +void use() { + capturePointer(getLifetimeBoundPointer(std::string()), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + capturePointer(getLifetimeBoundPointer(*getLifetimeBoundPointer( + std::string() // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + )), x); + capturePointer(getNotLifetimeBoundPointer(std::string()), x); + +} +} // namespace capture_pointer + +// **************************************************************************** +// Arrays and initializer lists. +// **************************************************************************** +namespace init_lists { +struct X {} x; +void captureVector(const std::vector &a [[clang::lifetime_capture_by(x)]], X &x); +void captureArray(int array [[clang::lifetime_capture_by(x)]] [2], X &x); +void captureInitList(std::initializer_list abc [[clang::lifetime_capture_by(x)]], X &x); + + +std::initializer_list getLifetimeBoundInitList(std::initializer_list abc [[clang::lifetimebound]]); + +void use() { + captureVector({1, 2, 3}, x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureVector(std::vector{}, x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + std::vector local_vector; + captureVector(local_vector, x); + int local_array[2]; + captureArray(local_array, x); + captureInitList({1, 2}, x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureInitList(getLifetimeBoundInitList({1, 2}), x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} +} +} // namespace init_lists + +// **************************************************************************** +// Implicit object param 'this' is captured +// **************************************************************************** +namespace this_is_captured { +struct X {} x; +struct S { + void capture(X &x) [[clang::lifetime_capture_by(x)]]; +}; +void use() { + S{}.capture(x); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + S s; + s.capture(x); +} +} // namespace this_is_captured + +// **************************************************************************** +// Capture by Global and Unknown. +// **************************************************************************** +namespace capture_by_global_unknown { +void captureByGlobal(std::string_view s [[clang::lifetime_capture_by(global)]]); +void captureByUnknown(std::string_view s [[clang::lifetime_capture_by(unknown)]]); + +std::string_view getLifetimeBoundView(const std::string& s [[clang::lifetimebound]]); + +void use() { + std::string_view local_string_view; + std::string local_string; + // capture by global. + captureByGlobal(std::string()); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}} + captureByGlobal(getLifetimeBoundView(std::string())); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}} + captureByGlobal(local_string); + captureByGlobal(local_string_view); + + // capture by unknown. + captureByUnknown(std::string()); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}} + captureByUnknown(getLifetimeBoundView(std::string())); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}} + captureByUnknown(local_string); + captureByUnknown(local_string_view); +} +} // namespace capture_by_global_unknown + +// **************************************************************************** +// Member functions: Capture by 'this' +// **************************************************************************** +namespace capture_by_this { +struct S { + void captureInt(const int& x [[clang::lifetime_capture_by(this)]]); + void captureView(std::string_view sv [[clang::lifetime_capture_by(this)]]); +}; +std::string_view getLifetimeBoundView(const std::string& s [[clang::lifetimebound]]); +std::string_view getNotLifetimeBoundView(const std::string& s); +const std::string& getLifetimeBoundString(const std::string &s [[clang::lifetimebound]]); + +void use() { + S s; + s.captureInt(1); // expected-warning {{object whose reference is captured by 's' will be destroyed at the end of the full-expression}} + s.captureView(std::string()); // expected-warning {{object whose reference is captured by 's' will be destroyed at the end of the full-expression}} + s.captureView(getLifetimeBoundView(std::string())); // expected-warning {{object whose reference is captured by 's' will be destroyed at the end of the full-expression}} + s.captureView(getLifetimeBoundString(std::string())); // expected-warning {{object whose reference is captured by 's' will be destroyed at the end of the full-expression}} + s.captureView(getNotLifetimeBoundView(std::string())); +} +} // namespace capture_by_this + +// **************************************************************************** +// Struct with field as a reference +// **************************************************************************** +namespace reference_field { +struct X {} x; +struct Foo { + const int& b; +}; +void captureField(Foo param [[clang::lifetime_capture_by(x)]], X &x); +void use() { + captureField(Foo{ + 1 // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + }, x); + int local; + captureField(Foo{local}, x); +} +} // namespace reference_field + +// **************************************************************************** +// Capture default argument. +// **************************************************************************** +namespace default_arg { +struct X {} x; +void captureDefaultArg(X &x, std::string_view s [[clang::lifetime_capture_by(x)]] = std::string()); + +std::string_view getLifetimeBoundView(const std::string& s [[clang::lifetimebound]]); + +void useCaptureDefaultArg() { + X x; + captureDefaultArg(x); // FIXME: Diagnose temporary default arg. + captureDefaultArg(x, std::string("temp")); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + captureDefaultArg(x, getLifetimeBoundView(std::string())); // expected-warning {{object whose reference is captured by 'x' will be destroyed at the end of the full-expression}} + std::string local; + captureDefaultArg(x, local); +} +} // namespace default_arg + +// **************************************************************************** +// Container: *No* distinction between pointer-like and other element type +// **************************************************************************** +namespace containers_no_distinction { +template +struct MySet { + void insert(T&& t [[clang::lifetime_capture_by(this)]]); + void insert(const T& t [[clang::lifetime_capture_by(this)]]); +}; +void user_defined_containers() { + MySet set_of_int; + set_of_int.insert(1); // expected-warning {{object whose reference is captured by 'set_of_int' will be destroyed at the end of the full-expression}} + MySet set_of_sv; + set_of_sv.insert(std::string()); // expected-warning {{object whose reference is captured by 'set_of_sv' will be destroyed at the end of the full-expression}} + set_of_sv.insert(std::string_view()); +} +} // namespace containers_no_distinction + +// **************************************************************************** +// Container: Different for pointer-like and other element type. +// **************************************************************************** +namespace conatiners_with_different { +template struct IsPointerLikeTypeImpl : std::false_type {}; +template<> struct IsPointerLikeTypeImpl : std::true_type {}; +template concept IsPointerLikeType = std::is_pointer::value || IsPointerLikeTypeImpl::value; + +template struct MyVector { + void push_back(T&& t [[clang::lifetime_capture_by(this)]]) requires IsPointerLikeType; + void push_back(const T& t [[clang::lifetime_capture_by(this)]]) requires IsPointerLikeType; + + void push_back(T&& t) requires (!IsPointerLikeType); + void push_back(const T& t) requires (!IsPointerLikeType); +}; + +std::string_view getLifetimeBoundView(const std::string& s [[clang::lifetimebound]]); + +void use_container() { + std::string local; + + MyVector vector_of_string; + vector_of_string.push_back(std::string()); // Ok. + + MyVector vector_of_view; + vector_of_view.push_back(std::string()); // expected-warning {{object whose reference is captured by 'vector_of_view' will be destroyed at the end of the full-expression}} + vector_of_view.push_back(getLifetimeBoundView(std::string())); // expected-warning {{object whose reference is captured by 'vector_of_view' will be destroyed at the end of the full-expression}} + + MyVector vector_of_pointer; + vector_of_pointer.push_back(getLifetimeBoundPointer(std::string())); // expected-warning {{object whose reference is captured by 'vector_of_pointer' will be destroyed at the end of the full-expression}} + vector_of_pointer.push_back(getLifetimeBoundPointer(*getLifetimeBoundPointer(std::string()))); // expected-warning {{object whose reference is captured by 'vector_of_pointer' will be destroyed at the end of the full-expression}} + vector_of_pointer.push_back(getLifetimeBoundPointer(local)); + vector_of_pointer.push_back(getNotLifetimeBoundPointer(std::string())); +} + +// **************************************************************************** +// Container: For user defined view types +// **************************************************************************** +struct [[gsl::Pointer()]] MyStringView : public std::string_view { + MyStringView(); + MyStringView(std::string_view&&); + MyStringView(const MyStringView&); + MyStringView(const std::string&); +}; +template<> struct IsPointerLikeTypeImpl : std::true_type {}; + +std::optional getOptionalSV(); +std::optional getOptionalS(); +std::optional getOptionalMySV(); +MyStringView getMySV(); + +class MyStringViewNotPointer : public std::string_view {}; +std::optional getOptionalMySVNotP(); +MyStringViewNotPointer getMySVNotP(); + +std::string_view getLifetimeBoundView(const std::string& s [[clang::lifetimebound]]); +std::string_view getNotLifetimeBoundView(const std::string& s); +const std::string& getLifetimeBoundString(const std::string &s [[clang::lifetimebound]]); +const std::string& getLifetimeBoundString(std::string_view sv [[clang::lifetimebound]]); + +void use_my_view() { + std::string local; + MyVector vector_of_my_view; + vector_of_my_view.push_back(getMySV()); + vector_of_my_view.push_back(MyStringView{}); + vector_of_my_view.push_back(std::string_view{}); + vector_of_my_view.push_back(std::string{}); // expected-warning {{object whose reference is captured by 'vector_of_my_view' will be destroyed at the end of the full-expression}} + vector_of_my_view.push_back(getLifetimeBoundView(std::string{})); // expected-warning {{object whose reference is captured by 'vector_of_my_view' will be destroyed at the end of the full-expression}} + vector_of_my_view.push_back(getLifetimeBoundString(getLifetimeBoundView(std::string{}))); // expected-warning {{object whose reference is captured by 'vector_of_my_view' will be destroyed at the end of the full-expression}} + vector_of_my_view.push_back(getNotLifetimeBoundView(getLifetimeBoundString(getLifetimeBoundView(std::string{})))); + + // Use with container of other view types. + MyVector vector_of_view; + vector_of_view.push_back(getMySV()); + vector_of_view.push_back(getMySVNotP()); +} + +// **************************************************************************** +// Container: Use with std::optional (owner types) +// **************************************************************************** +void use_with_optional_view() { + MyVector vector_of_view; + + std::optional optional_of_view; + vector_of_view.push_back(optional_of_view.value()); + vector_of_view.push_back(getOptionalS().value()); // expected-warning {{object whose reference is captured by 'vector_of_view' will be destroyed at the end of the full-expression}} + + vector_of_view.push_back(getOptionalSV().value()); + vector_of_view.push_back(getOptionalMySV().value()); + vector_of_view.push_back(getOptionalMySVNotP().value()); +} +} // namespace conatiners_with_different + +// **************************************************************************** +// Capture 'temporary' views +// **************************************************************************** +namespace temporary_views { +void capture1(std::string_view s [[clang::lifetime_capture_by(x)]], std::vector& x); + +// Intended to capture the "string_view" itself +void capture2(const std::string_view& s [[clang::lifetime_capture_by(x)]], std::vector& x); +// Intended to capture the pointee of the "string_view" +void capture3(const std::string_view& s [[clang::lifetime_capture_by(x)]], std::vector& x); + +void use() { + std::vector x1; + capture1(std::string(), x1); // expected-warning {{object whose reference is captured by 'x1' will be destroyed at the end of the full-expression}} + capture1(std::string_view(), x1); + + std::vector x2; + // Clang considers 'const std::string_view&' to refer to the owner + // 'std::string' and not 'std::string_view'. Therefore no diagnostic here. + capture2(std::string_view(), x2); + capture2(std::string(), x2); // expected-warning {{object whose reference is captured by 'x2' will be destroyed at the end of the full-expression}} + + std::vector x3; + capture3(std::string_view(), x3); + capture3(std::string(), x3); // expected-warning {{object whose reference is captured by 'x3' will be destroyed at the end of the full-expression}} +} +} // namespace temporary_views diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp index 6a2af01ea5116cc7020f8941ffe0627109f71b79..c18ecd86ad06f0be9bb2a9aabde75695369ab7b5 100644 --- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s +#include "Inputs/lifetime-analysis.h" struct [[gsl::Owner(int)]] MyIntOwner { MyIntOwner(); int &operator*(); @@ -129,130 +130,6 @@ void initLocalGslPtrWithTempOwner() { global2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer global2 }} } -namespace __gnu_cxx { -template -struct basic_iterator { - basic_iterator operator++(); - T& operator*() const; - T* operator->() const; -}; - -template -bool operator!=(basic_iterator, basic_iterator); -} - -namespace std { -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; - -template -typename remove_reference::type &&move(T &&t) noexcept; - -template -auto data(const C &c) -> decltype(c.data()); - -template -auto begin(C &c) -> decltype(c.begin()); - -template -T *begin(T (&array)[N]); - -using size_t = decltype(sizeof(0)); - -template -struct initializer_list { - const T* ptr; size_t sz; -}; -template class allocator {}; -template > -struct vector { - typedef __gnu_cxx::basic_iterator iterator; - iterator begin(); - iterator end(); - const T *data() const; - vector(); - vector(initializer_list __l, - const Alloc& alloc = Alloc()); - - template - vector(InputIterator first, InputIterator __last); - - T &at(int n); -}; - -template -struct basic_string_view { - basic_string_view(); - basic_string_view(const T *); - const T *begin() const; -}; -using string_view = basic_string_view; - -template struct iter { - iter& operator-=(int); - - iter operator-(int _Off) const { - iter _Tmp = *this; - return _Tmp -= _Off; - } -}; - -template -struct basic_string { - basic_string(); - basic_string(const T *); - const T *c_str() const; - operator basic_string_view () const; - using const_iterator = iter; -}; -using string = basic_string; - -template -struct unique_ptr { - T &operator*(); - T *get() const; -}; - -template -struct optional { - optional(); - optional(const T&); - - template - optional(U&& t); - - template - optional(optional&& __t); - - T &operator*() &; - T &&operator*() &&; - T &value() &; - T &&value() &&; -}; -template -optional<__decay(T)> make_optional(T&&); - - -template -struct stack { - T &top(); -}; - -struct any {}; - -template -T any_cast(const any& operand); - -template -struct reference_wrapper { - template - reference_wrapper(U &&); -}; - -template -reference_wrapper ref(T& t) noexcept; -} struct Unannotated { typedef std::vector::iterator iterator; diff --git a/clang/test/SemaCUDA/spirv-attrs.cu b/clang/test/SemaCUDA/spirv-attrs.cu new file mode 100644 index 0000000000000000000000000000000000000000..6539421423ee11033f10c891825063163de4b5b5 --- /dev/null +++ b/clang/test/SemaCUDA/spirv-attrs.cu @@ -0,0 +1,18 @@ +// expected-no-diagnostics + +// RUN: %clang_cc1 -triple spirv64 -aux-triple x86_64-unknown-linux-gnu \ +// RUN: -fcuda-is-device -verify -fsyntax-only %s + +#include "Inputs/cuda.h" + +__attribute__((reqd_work_group_size(128, 1, 1))) +__global__ void reqd_work_group_size_128_1_1() {} + +__attribute__((work_group_size_hint(2, 2, 2))) +__global__ void work_group_size_hint_2_2_2() {} + +__attribute__((vec_type_hint(int))) +__global__ void vec_type_hint_int() {} + +__attribute__((intel_reqd_sub_group_size(64))) +__global__ void intel_reqd_sub_group_size_64() {} diff --git a/clang/test/SemaCXX/attr-annotate-ast.cpp b/clang/test/SemaCXX/attr-annotate-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad8e2c26e666fd5f376d08cf6ae52a760095bcc0 --- /dev/null +++ b/clang/test/SemaCXX/attr-annotate-ast.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=gnu++20 -fsyntax-only -ast-dump %s | FileCheck %s + +void f() { + [[clang::annotate("decl", 1)]] int i = 0; + [[clang::annotate("stmt", 2)]] i += 1; +[[clang::annotate("label", 3)]] label1: + i += 2; +} + +// CHECK: -FunctionDecl {{.*}} f 'void ()' +// CHECK: -VarDecl {{.*}} used i 'int' +// CHECK: -AnnotateAttr {{.*}} "decl" +// CHECK: -IntegerLiteral {{.*}} 'int' 1 +// CHECK: -AttributedStmt +// CHECK: -AnnotateAttr {{.*}} "stmt" +// CHECK: -IntegerLiteral {{.*}} 'int' 2 +// CHECK: -LabelStmt {{.*}} 'label1' +// CHECK: -AnnotateAttr {{.*}} "label" +// CHECK: -IntegerLiteral {{.*}} 'int' 3 +// CHECK: -CompoundAssignOperator + +template void g() { + [[clang::annotate("tmpl_decl", 4)]] T j = 0; + [[clang::annotate("tmpl_stmt", 5)]] j += 1; +[[clang::annotate("tmpl_label", 6)]] label2: + j += 2; +} + +// CHECK: -FunctionTemplateDecl {{.*}} g +// CHECK: -VarDecl {{.*}} referenced j 'T' +// CHECK: -AnnotateAttr {{.*}} "tmpl_decl" +// CHECK: -IntegerLiteral {{.*}} 'int' 4 +// CHECK: -AttributedStmt +// CHECK: -AnnotateAttr {{.*}} "tmpl_stmt" +// CHECK: -IntegerLiteral {{.*}} 'int' 5 +// CHECK: -LabelStmt {{.*}} 'label2' +// CHECK: -AnnotateAttr {{.*}} "tmpl_label" +// CHECK: -IntegerLiteral {{.*}} 'int' 6 +// CHECK: -CompoundAssignOperator + +void h() { + g(); +} + +// CHECK: -FunctionDecl {{.*}} used g 'void ()' implicit_instantiation +// CHECK: -VarDecl {{.*}} used j 'int' +// CHECK: -AnnotateAttr {{.*}} "tmpl_decl" +// CHECK: -IntegerLiteral {{.*}} 'int' 4 +// CHECK: -AttributedStmt +// CHECK: -AnnotateAttr {{.*}} Implicit "tmpl_stmt" +// CHECK: -IntegerLiteral {{.*}} 'int' 5 +// CHECK: -LabelStmt {{.*}} 'label2' +// CHECK: -AnnotateAttr {{.*}} "tmpl_label" +// CHECK: -IntegerLiteral {{.*}} 'int' 6 +// CHECK: -CompoundAssignOperator diff --git a/clang/test/SemaCXX/attr-lifetime-capture-by.cpp b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp new file mode 100644 index 0000000000000000000000000000000000000000..be1cd730ed40ce7b37f77d92298f77da06ca1e41 --- /dev/null +++ b/clang/test/SemaCXX/attr-lifetime-capture-by.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++23 -verify %s + +struct S { + const int *x; + void captureInt(const int&x [[clang::lifetime_capture_by(this)]]) { this->x = &x; } +}; + +/////////////////////////// +// Test for valid usages. +/////////////////////////// +[[clang::lifetime_capture_by(unknown)]] // expected-error {{'lifetime_capture_by' attribute only applies to parameters and implicit object parameters}} +void nonMember( + const int &x1 [[clang::lifetime_capture_by(s, t)]], + S &s, + S &t, + const int &x2 [[clang::lifetime_capture_by(12345 + 12)]], // expected-error {{'lifetime_capture_by' attribute argument 12345 + 12 is not a known function parameter; must be a function parameter, 'this', 'global' or 'unknown'}} + const int &x3 [[clang::lifetime_capture_by(abcdefgh)]], // expected-error {{'lifetime_capture_by' attribute argument 'abcdefgh' is not a known function parameter; must be a function parameter, 'this', 'global' or 'unknown'}} + const int &x4 [[clang::lifetime_capture_by("abcdefgh")]], // expected-error {{'lifetime_capture_by' attribute argument "abcdefgh" is not a known function parameter; must be a function parameter, 'this', 'global' or 'unknown'}} + const int &x5 [[clang::lifetime_capture_by(this)]], // expected-error {{'lifetime_capture_by' argument references unavailable implicit 'this'}} + const int &x6 [[clang::lifetime_capture_by()]], // expected-error {{'lifetime_capture_by' attribute specifies no capturing entity}} + const int& x7 [[clang::lifetime_capture_by(u, + x7)]], // expected-error {{'lifetime_capture_by' argument references itself}} + const int &x8 [[clang::lifetime_capture_by(global)]], + const int &x9 [[clang::lifetime_capture_by(unknown)]], + const int &test_memory_leak[[clang::lifetime_capture_by(x1,x2, x3, x4, x5, x6, x7, x8, x9)]], + const S& u + ) +{ + s.captureInt(x1); +} + +void unknown_param_name(const int& unknown, // expected-error {{parameter cannot be named 'unknown' while using 'lifetime_capture_by(unknown)'}} + const int& s [[clang::lifetime_capture_by(unknown)]]); +void global_param_name(const int& global, // expected-error {{parameter cannot be named 'global' while using 'lifetime_capture_by(global)'}} + const int& s [[clang::lifetime_capture_by(global)]]); +struct T { + void member( + const int &x [[clang::lifetime_capture_by(s)]], + S &s, + S &t, + const int &y [[clang::lifetime_capture_by(s)]], + const int &z [[clang::lifetime_capture_by(this, x, y)]], + const int &u [[clang::lifetime_capture_by(global, unknown, x, s)]]) + { + s.captureInt(x); + } +}; diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp index 81e9193cf76a049792013f256b120cd350d84643..f89b556f5bba0885e70b7adac780f4891108ffb6 100644 --- a/clang/test/SemaCXX/attr-lifetimebound.cpp +++ b/clang/test/SemaCXX/attr-lifetimebound.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++23 -verify %s namespace usage_invalid { - void void_return(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void}} + void void_return(int ¶m [[clang::lifetimebound]]); // expected-error {{'lifetimebound' attribute cannot be applied to a parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}} int *not_class_member() [[clang::lifetimebound]]; // expected-error {{non-member function has no implicit object parameter}} struct A { @@ -11,7 +11,7 @@ namespace usage_invalid { int *explicit_object(this A&) [[clang::lifetimebound]]; // expected-error {{explicit object member function has no implicit object parameter}} int not_function [[clang::lifetimebound]]; // expected-error {{only applies to parameters and implicit object parameters}} int [[clang::lifetimebound]] also_not_function; // expected-error {{cannot be applied to types}} - void void_return_member() [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute cannot be applied to an implicit object parameter of a function that returns void}} + void void_return_member() [[clang::lifetimebound]]; // expected-error {{'lifetimebound' attribute cannot be applied to an implicit object parameter of a function that returns void; did you mean 'lifetime_capture_by(X)'}} }; int *attr_with_param(int ¶m [[clang::lifetimebound(42)]]); // expected-error {{takes no arguments}} } diff --git a/clang/test/SemaCXX/builtin-bit-cast.cpp b/clang/test/SemaCXX/builtin-bit-cast.cpp index 87919d9d9d28656e84311991117d07699059ea8b..8717371b941b0d3f89e38cff0d6418844e4b3224 100644 --- a/clang/test/SemaCXX/builtin-bit-cast.cpp +++ b/clang/test/SemaCXX/builtin-bit-cast.cpp @@ -24,7 +24,7 @@ void test1() { void test2() { constexpr int i = 0; - // expected-error@+1{{__builtin_bit_cast source size does not equal destination size (4 vs 1)}} + // expected-error@+1{{size of '__builtin_bit_cast' source type 'const int' does not match destination type 'char' (4 vs 1 bytes)}} constexpr char c = __builtin_bit_cast(char, i); } @@ -32,10 +32,10 @@ struct not_trivially_copyable { virtual void foo() {} }; -// expected-error@+1{{__builtin_bit_cast source type must be trivially copyable}} +// expected-error@+1{{'__builtin_bit_cast' source type must be trivially copyable}} constexpr unsigned long ul = __builtin_bit_cast(unsigned long, not_trivially_copyable{}); -// expected-error@+1 {{__builtin_bit_cast destination type must be trivially copyable}} +// expected-error@+1 {{'__builtin_bit_cast' destination type must be trivially copyable}} constexpr long us = __builtin_bit_cast(unsigned long &, 0L); namespace PR42936 { diff --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp index 5ddb77b35ff145edb370480a9520593830dc6aab..425447c5e604e9d23b274eab31268c093c91f276 100644 --- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp +++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp @@ -525,5 +525,5 @@ namespace test_complex { static_assert(TF.A == 1.0f && TF.B == 2.0f); constexpr double D = __builtin_bit_cast(double, test_float_complex); - constexpr int M = __builtin_bit_cast(int, test_int_complex); // expected-error {{__builtin_bit_cast source size does not equal destination size}} + constexpr int M = __builtin_bit_cast(int, test_int_complex); // expected-error {{size of '__builtin_bit_cast' source type 'const _Complex unsigned int' does not match destination type 'int' (8 vs 4 bytes)}} } diff --git a/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp b/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp index 25d1f8df7f71663a99dbacc022e1b9f9db821ff7..19e7d4976428a735299dd9599d81ca2103975249 100644 --- a/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp +++ b/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp @@ -1,7 +1,36 @@ -// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -Wimplicit-fallthrough -verify %s constexpr int f() { } // expected-warning {{non-void function does not return a value}} static_assert(__is_same(decltype([] constexpr -> int { }( )), int)); // expected-warning {{non-void lambda does not return a value}} consteval int g() { } // expected-warning {{non-void function does not return a value}} static_assert(__is_same(decltype([] consteval -> int { }( )), int)); // expected-warning {{non-void lambda does not return a value}} + +namespace GH116485 { +int h() { + if consteval { } +} // expected-warning {{non-void function does not return a value}} + +void i(int x) { + if consteval { + } + switch (x) { + case 1: + i(1); + case 2: // expected-warning {{unannotated fall-through between switch labels}} \ + // expected-note {{insert 'break;' to avoid fall-through}} + break; + } +} + +constexpr bool j() { + if !consteval { return true; } +} // expected-warning {{non-void function does not return a value in all control paths}} \ + // expected-note {{control reached end of constexpr function}} + +bool k = j(); +constinit bool l = j(); // expected-error {{variable does not have a constant initializer}} \ + // expected-note {{required by 'constinit' specifier here}} \ + // expected-note {{in call to 'j()'}} + +} diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index acf8d014a9896b952c4ad2d13c9c457e32615584..f3deb6ee3f4244f52c0a7203e60e962cf8d313ee 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -3,6 +3,11 @@ // RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,expected-cxx14 -fblocks %s // RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify=expected,not-cxx03 -ast-dump -fblocks %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,cxx03-cxx11,cxx11,expected-cxx14 -fblocks %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++03 -Wno-unused-value -fsyntax-only -verify=expected,cxx03,cxx03-cxx11,expected-cxx14 -fblocks %s -Ddecltype=__decltype -Dstatic_assert=_Static_assert -Wno-c++11-extensions -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,expected-cxx14 -fblocks %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify=expected,not-cxx03 -ast-dump -fblocks %s -fexperimental-new-constant-interpreter| FileCheck %s + namespace std { class type_info; }; namespace ExplicitCapture { diff --git a/clang/test/SemaCXX/warn-missing-noreturn.cpp b/clang/test/SemaCXX/warn-missing-noreturn.cpp index 400b471600e0277965cf7a8d0342d8a2ff04f06d..32b49e0a325f26641b542b4f60ad7caded2e6a74 100644 --- a/clang/test/SemaCXX/warn-missing-noreturn.cpp +++ b/clang/test/SemaCXX/warn-missing-noreturn.cpp @@ -122,3 +122,25 @@ namespace PR10801 { thingy(b); } } + +namespace GH63009 { +struct S1 { + [[noreturn]] S1(); +}; + +struct S2 { + [[noreturn]] ~S2(); +}; + +int foo(); + +int test_1() { + S1 s1; + foo(); +} + +int test_2() { + S2 s2; + foo(); +} +} diff --git a/clang/test/SemaCXX/warn-shadow.cpp b/clang/test/SemaCXX/warn-shadow.cpp index 2969bd39fed41e01c8f1dc5b2d48e9223704fa5f..98a235a73c7e52cc7a615b2034d0cf1213151736 100644 --- a/clang/test/SemaCXX/warn-shadow.cpp +++ b/clang/test/SemaCXX/warn-shadow.cpp @@ -307,3 +307,17 @@ void test4() { } }; // namespace structured_binding_tests + +namespace GH62588 { +class Outer { +public: + char *foo(); // expected-note {{previous declaration is here}} \ + // expected-note {{previous definition is here}} + enum Outer_E { foo }; // expected-error {{redefinition of 'foo'}} \ + // expected-warning {{declaration shadows a static data member of 'GH62588::Outer'}} + class Inner { + public: + enum Inner_E { foo }; // ok + }; +}; +} // namespace GH62588 diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp index 724d444638b57e7a3e02ea7c844aa05945bcd2c4..bfc34b55c1f66785d627c41a0de888d09cee505c 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-function-attr.cpp @@ -111,37 +111,6 @@ int testFoldExpression(Vs&&... v) { return (... + v); // expected-warning{{function introduces unsafe buffer manipulation}} } -struct HoldsUnsafeMembers { - HoldsUnsafeMembers() - : FromCtor(3), // expected-warning{{function introduces unsafe buffer manipulation}} - FromCtor2{3} // expected-warning{{function introduces unsafe buffer manipulation}} - {} - - [[clang::unsafe_buffer_usage]] - HoldsUnsafeMembers(int i) - : FromCtor(i), // expected-warning{{function introduces unsafe buffer manipulation}} - FromCtor2{i} // expected-warning{{function introduces unsafe buffer manipulation}} - {} - - HoldsUnsafeMembers(float f) - : HoldsUnsafeMembers(0) {} // expected-warning{{function introduces unsafe buffer manipulation}} - - UnsafeMembers FromCtor; - UnsafeMembers FromCtor2; - UnsafeMembers FromField{3}; // expected-warning 2{{function introduces unsafe buffer manipulation}} -}; - -struct SubclassUnsafeMembers : public UnsafeMembers { - SubclassUnsafeMembers() - : UnsafeMembers(3) // expected-warning{{function introduces unsafe buffer manipulation}} - {} - - [[clang::unsafe_buffer_usage]] - SubclassUnsafeMembers(int i) - : UnsafeMembers(i) // expected-warning{{function introduces unsafe buffer manipulation}} - {} -}; - // https://github.com/llvm/llvm-project/issues/80482 void testClassMembers() { UnsafeMembers(3); // expected-warning{{function introduces unsafe buffer manipulation}} @@ -153,95 +122,4 @@ void testClassMembers() { UnsafeMembers()(); // expected-warning{{function introduces unsafe buffer manipulation}} testFoldExpression(UnsafeMembers(), UnsafeMembers()); - - HoldsUnsafeMembers(); - HoldsUnsafeMembers(3); // expected-warning{{function introduces unsafe buffer manipulation}} - - SubclassUnsafeMembers(); - SubclassUnsafeMembers(3); // expected-warning{{function introduces unsafe buffer manipulation}} -} - -// Not an aggregate, so its constructor is not implicit code and will be -// visited/checked for warnings. -struct NotCalledHoldsUnsafeMembers { - NotCalledHoldsUnsafeMembers() - : FromCtor(3), // expected-warning{{function introduces unsafe buffer manipulation}} - FromCtor2{3} // expected-warning{{function introduces unsafe buffer manipulation}} - {} - - UnsafeMembers FromCtor; - UnsafeMembers FromCtor2; - UnsafeMembers FromField{3}; // expected-warning{{function introduces unsafe buffer manipulation}} -}; - -// An aggregate, so its constructor is implicit code. Since it's not called, it -// is never generated. -struct AggregateUnused { - UnsafeMembers f1; - // While this field would trigger the warning during initialization, since - // it's unused, there's no code generated that does the initialization, so - // no warning. - UnsafeMembers f2{3}; -}; - -struct AggregateExplicitlyInitializedSafe { - UnsafeMembers f1; - // The warning is not fired as the field is always explicltly initialized - // elsewhere. This initializer is never used. - UnsafeMembers f2{3}; -}; - -void testAggregateExplicitlyInitializedSafe() { - AggregateExplicitlyInitializedSafe A{ - .f2 = UnsafeMembers(), // A safe constructor. - }; } - -struct AggregateExplicitlyInitializedUnsafe { - UnsafeMembers f1; - // The warning is not fired as the field is always explicltly initialized - // elsewhere. This initializer is never used. - UnsafeMembers f2{3}; -}; - -void testAggregateExplicitlyInitializedUnsafe() { - AggregateExplicitlyInitializedUnsafe A{ - .f2 = UnsafeMembers(3), // expected-warning{{function introduces unsafe buffer manipulation}} - }; -} - -struct AggregateViaAggregateInit { - UnsafeMembers f1; - // FIXME: A construction of this class does initialize the field through - // this initializer, so it should warn. Ideally it should also point to - // where the site of the construction is in testAggregateViaAggregateInit(). - UnsafeMembers f2{3}; -}; - -void testAggregateViaAggregateInit() { - AggregateViaAggregateInit A{}; -}; - -struct AggregateViaValueInit { - UnsafeMembers f1; - // FIXME: A construction of this class does initialize the field through - // this initializer, so it should warn. Ideally it should also point to - // where the site of the construction is in testAggregateViaValueInit(). - UnsafeMembers f2{3}; -}; - -void testAggregateViaValueInit() { - auto A = AggregateViaValueInit(); -}; - -struct AggregateViaDefaultInit { - UnsafeMembers f1; - // FIXME: A construction of this class does initialize the field through - // this initializer, so it should warn. Ideally it should also point to - // where the site of the construction is in testAggregateViaValueInit(). - UnsafeMembers f2{3}; -}; - -void testAggregateViaDefaultInit() { - AggregateViaDefaultInit A; -}; diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp index c138fe088b3ba9724ae5e0f4e1c3e64a0271c69d..638c76c58c0250cc4d8204cf508127a927d3c5bd 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-in-container-span-construct.cpp @@ -21,6 +21,12 @@ namespace std { template< class T > T&& move( T&& t ) noexcept; + + template + _Tp* addressof(_Tp& __x) { + return &__x; + } + } namespace irrelevant_constructors { @@ -74,15 +80,26 @@ namespace construct_wt_ptr_size { return std::span{p, 10}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} } + // addressof method defined outside std namespace. + template + _Tp* addressof(_Tp& __x) { + return &__x; + } + void notWarnSafeCases(unsigned n, int *p) { int X; unsigned Y = 10; std::span S = std::span{&X, 1}; // no-warning + S = std::span{std::addressof(X), 1}; // no-warning int Arr[10]; typedef int TenInts_t[10]; TenInts_t Arr2; S = std::span{&X, 2}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} + S = std::span{std::addressof(X), 2}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} + // Warn when a non std method also named addressof + S = std::span{addressof(X), 1}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} + S = std::span{new int[10], 10}; // no-warning S = std::span{new int[n], n}; // no-warning S = std::span{new int, 1}; // no-warning @@ -157,23 +174,3 @@ namespace test_flag { } } //namespace test_flag - -struct HoldsStdSpanAndInitializedInCtor { - char* Ptr; - unsigned Size; - std::span Span{Ptr, Size}; // no-warning (this code is unreachable) - - HoldsStdSpanAndInitializedInCtor(char* P, unsigned S) - : Span(P, S) // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} - {} -}; - -struct HoldsStdSpanAndNotInitializedInCtor { - char* Ptr; - unsigned Size; - std::span Span{Ptr, Size}; // expected-warning{{the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information}} - - HoldsStdSpanAndNotInitializedInCtor(char* P, unsigned S) - : Ptr(P), Size(S) - {} -}; diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp index 0228e42652bd95eb8101d7e60252455ba4556cb7..a6a334d247023c88bc788e47a81b03dbe3d5da34 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-data-invocation.cpp @@ -173,4 +173,21 @@ A false_negatives(std::span span_pt, span span_A) { return *a2; // TODO: Can cause OOB if span_pt is empty } + +void test_incomplete_type(std::span S) { + (struct IncompleteStruct *)S.data(); // expected-warning{{unsafe invocation of 'data'}} + (class IncompleteClass *)S.data(); // expected-warning{{unsafe invocation of 'data'}} + (union IncompleteUnion *)S.data(); // expected-warning{{unsafe invocation of 'data'}} +} + +void test_complete_type(std::span S) { + (struct CompleteStruct *)S.data(); // no warn as the struct size is smaller than long + (class CompleteClass *)S.data(); // no warn as the class size is smaller than long + (union CompleteUnion *)S.data(); // no warn as the union size is smaller than long + + struct CompleteStruct {}; + class CompleteClass {}; + union CompleteUnion {}; +} + #endif diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp index 4b7a2503ecc0dd519823d713e7268b69098a71de..682c500dc1d96d6efde3c0bf9e9833639e22bc32 100644 --- a/clang/test/SemaCXX/warn-unused-result.cpp +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -108,7 +108,7 @@ void lazy() { (void)DoAnotherThing(); (void)DoYetAnotherThing(); - DoSomething(); // expected-warning {{ignoring return value}} + DoSomething(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} DoSomethingElse(); DoAnotherThing(); DoYetAnotherThing(); @@ -120,11 +120,11 @@ class [[clang::warn_unused_result]] StatusOr { StatusOr doit(); void test() { Foo f; - f.doStuff(); // expected-warning {{ignoring return value}} - doit(); // expected-warning {{ignoring return value}} + f.doStuff(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} + doit(); // expected-warning {{ignoring return value of type 'StatusOr' declared with 'warn_unused_result'}} auto func = []() { return Status(); }; - func(); // expected-warning {{ignoring return value}} + func(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} } } @@ -139,7 +139,7 @@ struct Status {}; void Bar() { Foo f; - f.Bar(); // expected-warning {{ignoring return value}} + f.Bar(); // expected-warning {{ignoring return value of type 'Status' declared with 'warn_unused_result'}} }; } @@ -215,18 +215,18 @@ P operator--(const P &) { return {}; }; void f() { S s; P p; - s.DoThing(); // expected-warning {{ignoring return value}} - p.DoThing(); // expected-warning {{ignoring return value}} + s.DoThing(); // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} + p.DoThing(); // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} // Only postfix is expected to warn when written correctly. - s++; // expected-warning {{ignoring return value}} - s--; // expected-warning {{ignoring return value}} - p++; // expected-warning {{ignoring return value}} - p--; // expected-warning {{ignoring return value}} + s++; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} + s--; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} + p++; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} + p--; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} // Improperly written prefix operators should still warn. - ++s; // expected-warning {{ignoring return value}} - --s; // expected-warning {{ignoring return value}} - ++p; // expected-warning {{ignoring return value}} - --p; // expected-warning {{ignoring return value}} + ++s; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} + --s; // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} + ++p; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} + --p; // expected-warning {{ignoring return value of type 'P' declared with 'warn_unused_result'}} // Silencing the warning by cast to void still works. (void)s.DoThing(); @@ -243,7 +243,7 @@ namespace PR39837 { void g() { int a[2]; for (int b : a) - f(b); // expected-warning {{ignoring return value}} + f(b); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} } } // namespace PR39837 @@ -261,12 +261,12 @@ typedef a indirect; a af1(); indirect indirectf1(); void af2() { - af1(); // expected-warning {{ignoring return value}} + af1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}} void *(*a1)(); a1(); // no warning a (*a2)(); - a2(); // expected-warning {{ignoring return value}} - indirectf1(); // expected-warning {{ignoring return value}} + a2(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}} + indirectf1(); // expected-warning {{ignoring return value of type 'a' declared with 'warn_unused_result'}} } [[nodiscard]] typedef void *b1; // expected-warning {{'[[nodiscard]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}} [[gnu::warn_unused_result]] typedef void *b2; // expected-warning {{'[[gnu::warn_unused_result]]' attribute ignored when applied to a typedef; consider using '__attribute__((warn_unused_result))' or '[[clang::warn_unused_result]]' instead}} @@ -279,10 +279,79 @@ void bf2() { __attribute__((warn_unused_result)) typedef void *c; c cf1(); void cf2() { - cf1(); // expected-warning {{ignoring return value}} + cf1(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}} void *(*c1)(); c1(); c (*c2)(); - c2(); // expected-warning {{ignoring return value}} + c2(); // expected-warning {{ignoring return value of type 'c' declared with 'warn_unused_result'}} } } + +namespace nodiscard_specialization { +// Test to only mark a specialization of class template as nodiscard +template struct S { S(int) {} }; +template<> struct [[nodiscard]] S { S(int) {} }; +template struct [[clang::warn_unused_result]] S { S(int) {} }; + +template +S obtain(const T&) { return {2}; } + +template +[[nodiscard]] S obtain2(const T&) { return {2}; } + +template +__attribute__((warn_unused_result)) S obtain3(const T&) { return {2}; } + +void use() { + obtain(1.0); // no warning + obtain(1); // expected-warning {{ignoring return value of type 'S' declared with 'nodiscard'}} + obtain(1); // expected-warning {{ignoring return value of type 'S' declared with 'warn_unused_result'}} + + S(2); // no warning + S(2); // expected-warning {{ignoring temporary of type 'S' declared with 'nodiscard'}} + S(2); // no warning (warn_unused_result does not diagnose constructor temporaries) + + // function should take precedence over type + obtain2(1.0); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} + obtain2(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} + obtain2(1); // expected-warning {{ignoring return value of function declared with 'nodiscard'}} + obtain3(1.0); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} + obtain3(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} + obtain3(1); // expected-warning {{ignoring return value of function declared with 'warn_unused_result'}} +} + +// Test on constructor nodiscard +struct H { + explicit H(int) {} + [[nodiscard]] explicit H(double) {} + __attribute__((warn_unused_result)) H(const char*) {} +}; + +struct [[nodiscard]] G { + explicit G(int) {} + [[nodiscard]] explicit G(double) {} + [[clang::warn_unused_result]] G(const char*) {} +}; + +void use2() { + H{2}; // no warning + H(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}} + H("Hello"); // no warning (warn_unused_result does not diagnose constructor temporaries) + + // no warning for explicit cast to void + (void)H(2); + (void)H{2.0}; + (void)H{"Hello"}; + + // warns for all these invocations + // here, constructor/function should take precedence over type + G{2}; // expected-warning {{ignoring temporary of type 'G' declared with 'nodiscard'}} + G(2.0); // expected-warning {{ignoring temporary created by a constructor declared with 'nodiscard'}} + G("Hello"); // expected-warning {{ignoring temporary created by a constructor declared with 'warn_unused_result'}} + + // no warning for explicit cast to void + (void)G(2); + (void)G{2.0}; + (void)G{"Hello"}; +} +} // namespace nodiscard_specialization diff --git a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl index 76b5d01b8036eb32a32e3baf3abf4b47369ea9cb..3c2ea557b1982be5b74f1afebc60b8a7c99c6314 100644 --- a/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl @@ -14,6 +14,6 @@ RWBuffer<> BufferErr2; [numthreads(1,1,1)] void main() { - (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::RWBuffer>'}} + (void)Buffer.__handle; // expected-error {{'__handle' is a private member of 'hlsl::RWBuffer>'}} // expected-note@* {{implicitly declared private here}} } diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl index a472d5519dc51fcccf166f62948fe400109335d8..b0cf9453cecfcfe456aaef3694592b6f7c97ff5b 100644 --- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl @@ -14,6 +14,6 @@ StructuredBuffer<> BufferErr2; [numthreads(1,1,1)] void main() { - (void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::StructuredBuffer>'}} + (void)Buffer.__handle; // expected-error {{'__handle' is a private member of 'hlsl::StructuredBuffer>'}} // expected-note@* {{implicitly declared private here}} } diff --git a/clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..871e512e128c547c35c9c0f6139f99eaf7333600 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/clip-errors.hlsl @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -verify + + +void test_arg_missing() { + __builtin_hlsl_elementwise_clip(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +void test_too_many_args(float p1, float p2) { + __builtin_hlsl_elementwise_clip(p1, p2); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +void test_first_arg_type_mismatch(bool p) { + __builtin_hlsl_elementwise_clip(p); + // expected-error@-1 {{invalid operand of type 'bool' where 'float' or a vector of such type is required}} +} + +void test_first_arg_type_mismatch_3(half3 p) { + __builtin_hlsl_elementwise_clip(p); + // expected-error@-1 {{invalid operand of type 'half3' (aka 'vector') where 'float' or a vector of such type is required}} +} + +void test_first_arg_type_mismatch_3(double p) { + __builtin_hlsl_elementwise_clip(p); + // expected-error@-1 {{invalid operand of type 'double' where 'float' or a vector of such type is required}} +} diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl index acc1f281daddfc8f12f9a7598b9635eead73de12..0467844e1cab8c5c084600eb6eb633aa5008626d 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl @@ -1,109 +1,52 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s // expected-no-diagnostics -struct oneInt { - int i; -}; - -struct twoInt { - int aa; - int ab; -}; - -struct threeInts { - oneInt o; - twoInt t; -}; - -struct oneFloat { - float f; -}; -struct depthDiff { - int i; - oneInt o; - oneFloat f; -}; - -struct notHomogenous{ - int i; - float f; -}; - -struct EightElements { - twoInt x[2]; - twoInt y[2]; -}; - -struct EightHalves { -half x[8]; -}; - -struct intVec { - int2 i; -}; - -struct oneIntWithVec { - int i; - oneInt i2; - int2 i3; -}; - -struct weirdStruct { - int i; - intVec iv; -}; _Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(int), ""); _Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float), ""); _Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float4), ""); _Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(double2), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneInt), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneFloat), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(twoInt), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(threeInts), ""); -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notHomogenous), ""); -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(depthDiff), ""); -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightElements), ""); -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightHalves), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneIntWithVec), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(weirdStruct), ""); + _Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(RWBuffer), ""); +struct s { + int x; +}; -// arrays not allowed -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(half[4]), ""); +struct Empty {}; template struct TemplatedBuffer { T a; - __hlsl_resource_t h; }; -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(TemplatedBuffer), ""); -struct MyStruct1 : TemplatedBuffer { - float x; +template struct TemplatedVector { + vector v; }; -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct1), ""); -struct MyStruct2 { - const TemplatedBuffer TB[10]; -}; -_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct2), ""); +// structs not allowed +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(s), ""); +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(Empty), ""); +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(TemplatedBuffer), ""); +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(TemplatedVector), ""); -template struct SimpleTemplate { - T a; -}; +// arrays not allowed +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(half[4]), ""); -// though the element type is incomplete, the type trait should still technically return true -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate<__hlsl_resource_t>), ""); +typedef vector int8; +// too many elements +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(int8), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate), ""); +typedef int MyInt; +_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(MyInt), ""); +// bool and enums not allowed +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(bool), ""); +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(vector), ""); -typedef int myInt; +enum numbers { one, two, three }; -struct TypeDefTest { - int x; - myInt y; -}; +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(numbers), ""); + +// size exceeds 16 bytes, and exceeds element count limit after splitting 64 bit types into 32 bit types +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(double3), ""); -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(TypeDefTest), ""); diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl index cb3e9ae7a61509a11fb32740584ac05866461d13..d3d79aa0499e54b35edb798659423dc506ee42de 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl @@ -1,10 +1,9 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s // types must be complete -_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(__hlsl_resource_t), ""); +_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(__hlsl_resource_t), ""); // expected-note@+1{{forward declaration of 'notComplete'}} struct notComplete; // expected-error@+1{{incomplete type 'notComplete' where a complete type is required}} _Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notComplete), ""); - diff --git a/clang/test/SemaObjC/comptypes-legal.m b/clang/test/SemaObjC/comptypes-legal.m index 09c3a7261bd58b8b839e124f33d1228cd17b7c95..8e332f42be842903e6a372409412f82c216d989f 100644 --- a/clang/test/SemaObjC/comptypes-legal.m +++ b/clang/test/SemaObjC/comptypes-legal.m @@ -41,7 +41,7 @@ void foo(void) - (void) Meth : (id )aKey; // expected-note {{passing argument to parameter 'aKey' here}} @end -@class ForwarClass; // expected-note 3 {{conformance of forward class 'ForwarClass' to protocol 'NSCopying' can not be confirmed}} +@class ForwarClass; // expected-note 3 {{conformance of forward class 'ForwarClass' to protocol 'NSCopying' cannot be confirmed}} ForwarClass *Test10751015 (I* pi, ForwarClass *ns_forward) { diff --git a/clang/test/SemaObjC/method-param-named-id.m b/clang/test/SemaObjC/method-param-named-id.m new file mode 100644 index 0000000000000000000000000000000000000000..8269c31116c32d87bb979d21b69e77d194c78d99 --- /dev/null +++ b/clang/test/SemaObjC/method-param-named-id.m @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s + + +@interface Foo +-(void)paramNamedID:(int)id usesIDType:(id)notShadowed; +-(void)paramNamedID:(int)id, id notShadowed; // expected-warning{{use of C-style parameters in Objective-C method declarations is deprecated}} +@end diff --git a/clang/test/SemaOpenACC/combined-construct-ast.cpp b/clang/test/SemaOpenACC/combined-construct-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b818e3aa12e01895543cda1e93c21a628323f9c --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-ast.cpp @@ -0,0 +1,228 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER + +void NormalFunc() { + // CHECK-LABEL: NormalFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop + for(int i = 0; i < 5;++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}i + // CHECK-NEXT: IntegerLiteral {{.*}}'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator {{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral {{.*}}'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} '++' + // CHECK-NEXT: DeclRefExpr{{.*}}'i' + // CHECK-NEXT: NullStmt + +#pragma acc serial loop + for(int i = 0; i < 5;++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}i + // CHECK-NEXT: IntegerLiteral {{.*}}'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator {{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral {{.*}}'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} '++' + // CHECK-NEXT: DeclRefExpr{{.*}}'i' + // CHECK-NEXT: NullStmt + +#pragma acc kernels loop + for(int i = 0; i < 5;++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}}i + // CHECK-NEXT: IntegerLiteral {{.*}}'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator {{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral {{.*}}'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} '++' + // CHECK-NEXT: DeclRefExpr{{.*}}'i' + // CHECK-NEXT: NullStmt + + + int array[5]; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl +#pragma acc parallel loop + for(auto x : array){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: CXXForRangeStmt + // CHECK: CompoundStmt + +#pragma acc parallel + // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel + // CHECK-NEXT: CompoundStmt + { +#pragma acc serial loop + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}}serial loop + // CHECK-NEXT: CXXForRangeStmt + // CHECK: CompoundStmt + for(auto x: array) { +#pragma acc loop + // CHECK-NEXT: OpenACCLoopConstruct{{.*}} parent: serial loop + // CHECK-NEXT: CXXForRangeStmt + // CHECK: CompoundStmt + for(auto y: array) { } + } + } +} +template +void TemplFunc() { + // CHECK-LABEL: FunctionTemplateDecl {{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc serial loop + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}} serial loop + for(typename T::type t = 0; t < 5;++t) { + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} referenced t 'typename T::type' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 + // CHECK-NEXT: <<> + // CHECK-NEXT: BinaryOperator{{.*}} '' '<' + // CHECK-NEXT: DeclRefExpr {{.*}} 'typename T::type' lvalue Var + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} '' lvalue prefix '++' + // CHECK-NEXT: DeclRefExpr {{.*}} 'typename T::type' lvalue Var + // CHECK-NEXT: CompoundStmt + typename T::type I; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} I 'typename T::type' + + } + +#pragma acc parallel loop + for(int a = 0; a < 5; ++a) { + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}} parallel loop + // CHECK-NEXT: ForStmt + // CHECK: CompoundStmt +#pragma acc kernels loop + for(int b = 0; b < 5; ++b) { + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}} kernels loop + // CHECK-NEXT: ForStmt + // CHECK: CompoundStmt +#pragma acc loop + // CHECK-NEXT: OpenACCLoopConstruct{{.*}} parent: kernels loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl {{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} prefix '++' + // CHECK-NEXT: DeclRefExpr{{.*}} 'i' 'int' + // CHECK-NEXT: NullStmt + for(int i = 0; i < 5;++i); + +#pragma acc loop + // CHECK-NEXT: OpenACCLoopConstruct{{.*}} parent: kernels loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl {{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} prefix '++' + // CHECK-NEXT: DeclRefExpr{{.*}} 'i' 'int' + // CHECK-NEXT: NullStmt + for(int i = 0; i < 5;++i); + } + } + + // Instantiation: + // CHECK-NEXT: FunctionDecl{{.*}} TemplFunc 'void ()' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'S' + // CHECK-NEXT: RecordType{{.*}} 'S' + // CHECK-NEXT: CXXRecord{{.*}} 'S' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}} serial loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} t 'typename S::type':'int' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 + // CHECK-NEXT: <<> + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr {{.*}} 'typename S::type':'int' lvalue Var + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} 'typename S::type':'int' lvalue prefix '++' + // CHECK-NEXT: DeclRefExpr {{.*}} 'typename S::type':'int' lvalue Var + // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int' + + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}} parallel loop + // CHECK-NEXT: ForStmt + // CHECK: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}} kernels loop + // CHECK-NEXT: ForStmt + // CHECK: CompoundStmt + + // CHECK-NEXT: OpenACCLoopConstruct{{.*}} parent: kernels loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl {{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} prefix '++' + // CHECK-NEXT: DeclRefExpr{{.*}} 'i' 'int' + // CHECK-NEXT: NullStmt + + // CHECK-NEXT: OpenACCLoopConstruct{{.*}} parent: kernels loop + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl {{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'bool' '<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr + // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}} prefix '++' + // CHECK-NEXT: DeclRefExpr{{.*}} 'i' 'int' + // CHECK-NEXT: NullStmt + +} + +struct S { + using type = int; +}; + +void use() { + TemplFunc(); +} +#endif diff --git a/clang/test/SemaOpenACC/combined-construct-async-clause.c b/clang/test/SemaOpenACC/combined-construct-async-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..c9ccbd65ad79e32a6ab13707392804f8f6df75a3 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-async-clause.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +short getS(); + +void Test() { +#pragma acc parallel loop async + for (int i = 5; i < 10; ++i); +#pragma acc parallel loop async(1) + for (int i = 5; i < 10; ++i); +#pragma acc kernels loop async(1) + for (int i = 5; i < 10; ++i); +#pragma acc kernels loop async(-51) + for (int i = 5; i < 10; ++i); + +#pragma acc serial loop async(1) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{expected ')'}} + // expected-note@+1{{to match this '('}} +#pragma acc serial loop async(1, 2) + for (int i = 5; i < 10; ++i); + + struct NotConvertible{} NC; + // expected-error@+1{{OpenACC clause 'async' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc parallel loop async(NC) + for (int i = 5; i < 10; ++i); + +#pragma acc kernels loop async(getS()) + for (int i = 5; i < 10; ++i); + + struct Incomplete *SomeIncomplete; + + // expected-error@+1{{OpenACC clause 'async' requires expression of integer type ('struct Incomplete' invalid)}} +#pragma acc kernels loop async(*SomeIncomplete) + for (int i = 5; i < 10; ++i); + + enum E{A} SomeE; + +#pragma acc kernels loop async(SomeE) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC 'async' clause is not valid on 'loop' directive}} +#pragma acc loop async(1) + for(int i = 5; i < 10;++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-async-clause.cpp b/clang/test/SemaOpenACC/combined-construct-async-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..872586acbaffa2bdc161cb5b9ff82e34a1532ce7 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-async-clause.cpp @@ -0,0 +1,137 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NotConvertible{} NC; +struct Incomplete *SomeIncomplete; // #INCOMPLETE +enum E{} SomeE; +enum class E2{} SomeE2; + +struct CorrectConvert { + operator int(); +} Convert; + +struct ExplicitConvertOnly { + explicit operator int() const; // #EXPL_CONV +} Explicit; + +struct AmbiguousConvert{ + operator int(); // #AMBIG_INT + operator short(); // #AMBIG_SHORT + operator float(); +} Ambiguous; + +void Test() { +#pragma acc parallel loop async + for (int i = 5; i < 10; ++i); +#pragma acc parallel loop async(1) + for (int i = 5; i < 10; ++i); +#pragma acc kernels loop async(-51) + for (int i = 5; i < 10; ++i); +#pragma acc serial loop async(2) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC clause 'async' requires expression of integer type ('struct NotConvertible' invalid}} +#pragma acc parallel loop async(NC) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{OpenACC integer expression has incomplete class type 'struct Incomplete'}} + // expected-note@#INCOMPLETE{{forward declaration of 'Incomplete'}} +#pragma acc kernels loop async(*SomeIncomplete) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop async(SomeE) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC clause 'async' requires expression of integer type ('enum E2' invalid}} +#pragma acc kernels loop async(SomeE2) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop async(Convert) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{OpenACC integer expression type 'struct ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc kernels loop async(Explicit) + for (int i = 5; i < 10; ++i); + + // expected-error@+3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc parallel loop async(Ambiguous) + for (int i = 5; i < 10; ++i); +} + +struct HasInt { + using IntTy = int; + using ShortTy = short; + static constexpr int value = 1; + static constexpr AmbiguousConvert ACValue; + static constexpr ExplicitConvertOnly EXValue; + + operator char(); +}; + +template +void TestInst() { + + // expected-error@+1{{no member named 'Invalid' in 'HasInt'}} +#pragma acc parallel loop async(HasInt::Invalid) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{no member named 'Invalid' in 'HasInt'}} + // expected-note@#INST{{in instantiation of function template specialization 'TestInst' requested here}} +#pragma acc kernels loop async(T::Invalid) + for (int i = 5; i < 10; ++i); + + // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc parallel loop async(HasInt::ACValue) + for (int i = 5; i < 10; ++i); + + // expected-error@+3{{multiple conversions from expression type 'const AmbiguousConvert' to an integral type}} + // expected-note@#AMBIG_INT{{conversion to integral type 'int'}} + // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}} +#pragma acc kernels loop async(T::ACValue) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc parallel loop async(HasInt::EXValue) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{OpenACC integer expression type 'const ExplicitConvertOnly' requires explicit conversion to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} +#pragma acc kernels loop async(T::EXValue) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop async(HasInt::value) + for (int i = 5; i < 10; ++i); + +#pragma acc kernels loop async(T::value) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop async(HasInt::IntTy{}) + for (int i = 5; i < 10; ++i); + +#pragma acc kernels loop async(typename T::ShortTy{}) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop async(HasInt::IntTy{}) + for (int i = 5; i < 10; ++i); + +#pragma acc kernels loop async(typename T::ShortTy{}) + for (int i = 5; i < 10; ++i); + + HasInt HI{}; + T MyT{}; + +#pragma acc parallel loop async(HI) + for (int i = 5; i < 10; ++i); + +#pragma acc kernels loop async(MyT) + for (int i = 5; i < 10; ++i); +} + +void Inst() { + TestInst(); // #INST +} diff --git a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-ast.cpp b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc641fdff32d63d1ab4a835b683d383d48118f25 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-ast.cpp @@ -0,0 +1,160 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER + +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop auto + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: auto clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt + +#pragma acc serial loop seq + for(;;){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: seq clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels loop independent + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: independent clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +} + +template +void TemplUses() { + // CHECK: FunctionTemplateDecl{{.*}}TemplUses + // CHECK-NEXT: TemplateTypeParmDecl + // CHECK-NEXT: FunctionDecl{{.*}} TemplUses + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop auto + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: auto clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt + +#pragma acc serial loop seq + for(;;){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: seq clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: CompoundStmt + +#pragma acc kernels loop independent + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: independent clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt + + // Instantiations. + // CHECK-NEXT: FunctionDecl{{.*}}TemplUses 'void ()' implicit_instantiation + // CHECK-NEXT: TemplateArgument + // CHECK-NEXT: BuiltinType + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: auto clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: seq clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: <<>> + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: independent clause + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +} + +void Inst() { + TemplUses(); +} +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c new file mode 100644 index 0000000000000000000000000000000000000000..a770020764d356889c960921ce1d2fe32b0bae43 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-auto_seq_independent-clauses.c @@ -0,0 +1,1032 @@ + +// RUN: %clang_cc1 %s -fopenacc -verify + +// TODO: OpenACC: A number of the 'not yet implemented' diagnostics interfere +// with the diagnostics we want to make here, so as we implement these, we need +// to replace the errors we should have. +void uses() { +#pragma acc parallel loop auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent + for(unsigned i = 0; i < 5; ++i); + + // expected-error@+2{{OpenACC clause 'seq' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop auto seq + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop auto independent + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop seq auto + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop seq independent + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop independent auto + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'seq' on 'parallel loop' construct conflicts with previous data dependence clause}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop independent seq + for(unsigned i = 0; i < 5; ++i); + + int Var; + int *VarPtr; + + // 'auto' can combine with any other clause. + // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} +#pragma acc parallel loop auto finalize + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc parallel loop auto if_present + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} +#pragma acc parallel loop auto worker + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} +#pragma acc parallel loop auto vector + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} +#pragma acc parallel loop auto nohost + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto default(none) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto if(1) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto self + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} +#pragma acc parallel loop auto copy(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'pcopy' not yet implemented}} +#pragma acc parallel loop auto pcopy(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'present_or_copy' not yet implemented}} +#pragma acc parallel loop auto present_or_copy(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented}} +#pragma acc parallel loop auto use_device(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'attach' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'attach' not yet implemented}} +#pragma acc parallel loop auto attach(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'delete' not yet implemented}} +#pragma acc parallel loop auto delete(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'detach' not yet implemented}} +#pragma acc parallel loop auto detach(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc parallel loop auto device(VarPtr) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'deviceptr' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'deviceptr' not yet implemented}} +#pragma acc parallel loop auto deviceptr(VarPtr) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented}} +#pragma acc parallel loop auto device_resident(VarPtr) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto firstprivate(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc parallel loop auto host(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'link' not yet implemented}} +#pragma acc parallel loop auto link(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'no_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'no_create' not yet implemented}} +#pragma acc parallel loop auto no_create(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'present' not yet implemented}} +#pragma acc parallel loop auto present(Var) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto private(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyout' not yet implemented}} +#pragma acc parallel loop auto copyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'pcopyout' not yet implemented}} +#pragma acc parallel loop auto pcopyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyout' not yet implemented}} +#pragma acc parallel loop auto present_or_copyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyin' not yet implemented}} +#pragma acc parallel loop auto copyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'pcopyin' not yet implemented}} +#pragma acc parallel loop auto pcopyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyin' not yet implemented}} +#pragma acc parallel loop auto present_or_copyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'create' not yet implemented}} +#pragma acc parallel loop auto create(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcreate' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcreate' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'pcreate' not yet implemented}} +#pragma acc parallel loop auto pcreate(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_create' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'present_or_create' not yet implemented}} +#pragma acc parallel loop auto present_or_create(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented}} +#pragma acc parallel loop auto reduction(+:Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented}} +#pragma acc parallel loop auto collapse(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'bind' not yet implemented}} +#pragma acc parallel loop auto bind(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'vector_length' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'vector_length' not yet implemented}} +#pragma acc parallel loop auto vector_length(1) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented}} +#pragma acc parallel loop auto num_gangs(1) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_workers' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented}} +#pragma acc parallel loop auto num_workers(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} +#pragma acc parallel loop auto device_num(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} +#pragma acc parallel loop auto default_async(1) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto device_type(*) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto dtype(*) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop auto async + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented}} +#pragma acc parallel loop auto tile(1+2, 1) + for(unsigned j = 0; j < 5; ++j) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} +#pragma acc parallel loop auto gang + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'wait' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc parallel loop auto wait + for(unsigned i = 0; i < 5; ++i); + + // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} +#pragma acc parallel loop finalize auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc parallel loop if_present auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} +#pragma acc parallel loop worker auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} +#pragma acc parallel loop vector auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} +#pragma acc parallel loop nohost auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop default(none) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop if(1) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop self auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} +#pragma acc parallel loop copy(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'pcopy' not yet implemented}} +#pragma acc parallel loop pcopy(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'present_or_copy' not yet implemented}} +#pragma acc parallel loop present_or_copy(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented}} +#pragma acc parallel loop use_device(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'attach' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'attach' not yet implemented}} +#pragma acc parallel loop attach(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'delete' not yet implemented}} +#pragma acc parallel loop delete(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'detach' not yet implemented}} +#pragma acc parallel loop detach(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc parallel loop device(VarPtr) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'deviceptr' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'deviceptr' not yet implemented}} +#pragma acc parallel loop deviceptr(VarPtr) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented}} +#pragma acc parallel loop device_resident(VarPtr) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop firstprivate(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc parallel loop host(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'link' not yet implemented}} +#pragma acc parallel loop link(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'no_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'no_create' not yet implemented}} +#pragma acc parallel loop no_create(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'present' not yet implemented}} +#pragma acc parallel loop present(Var) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop private(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyout' not yet implemented}} +#pragma acc parallel loop copyout(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'pcopyout' not yet implemented}} +#pragma acc parallel loop pcopyout(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyout' not yet implemented}} +#pragma acc parallel loop present_or_copyout(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyin' not yet implemented}} +#pragma acc parallel loop copyin(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'pcopyin' not yet implemented}} +#pragma acc parallel loop pcopyin(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyin' not yet implemented}} +#pragma acc parallel loop present_or_copyin(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'create' not yet implemented}} +#pragma acc parallel loop create(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcreate' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcreate' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'pcreate' not yet implemented}} +#pragma acc parallel loop pcreate(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_create' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'present_or_create' not yet implemented}} +#pragma acc parallel loop present_or_create(Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented}} +#pragma acc parallel loop reduction(+:Var) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented}} +#pragma acc parallel loop collapse(1) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'bind' not yet implemented}} +#pragma acc parallel loop bind(Var) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'vector_length' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'vector_length' not yet implemented}} +#pragma acc parallel loop vector_length(1) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented}} +#pragma acc parallel loop num_gangs(1) auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_workers' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented}} +#pragma acc parallel loop num_workers(1) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} +#pragma acc parallel loop device_num(1) auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} +#pragma acc parallel loop default_async(1) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop device_type(*) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop dtype(*) auto + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop async auto + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented}} +#pragma acc parallel loop tile(1+2, 1) auto + for(unsigned j = 0; j < 5; ++j) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} +#pragma acc parallel loop gang auto + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'wait' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc parallel loop wait auto + for(unsigned i = 0; i < 5; ++i); + + // 'independent' can also be combined with any clauses + // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} +#pragma acc parallel loop independent finalize + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc parallel loop independent if_present + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} +#pragma acc parallel loop independent worker + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} +#pragma acc parallel loop independent vector + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} +#pragma acc parallel loop independent nohost + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent default(none) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent if(1) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent self + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} +#pragma acc parallel loop independent copy(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'pcopy' not yet implemented}} +#pragma acc parallel loop independent pcopy(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'present_or_copy' not yet implemented}} +#pragma acc parallel loop independent present_or_copy(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented}} +#pragma acc parallel loop independent use_device(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'attach' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'attach' not yet implemented}} +#pragma acc parallel loop independent attach(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'delete' not yet implemented}} +#pragma acc parallel loop independent delete(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'detach' not yet implemented}} +#pragma acc parallel loop independent detach(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc parallel loop independent device(VarPtr) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'deviceptr' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'deviceptr' not yet implemented}} +#pragma acc parallel loop independent deviceptr(VarPtr) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented}} +#pragma acc parallel loop independent device_resident(VarPtr) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent firstprivate(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc parallel loop independent host(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'link' not yet implemented}} +#pragma acc parallel loop independent link(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'no_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'no_create' not yet implemented}} +#pragma acc parallel loop independent no_create(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'present' not yet implemented}} +#pragma acc parallel loop independent present(Var) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent private(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyout' not yet implemented}} +#pragma acc parallel loop independent copyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'pcopyout' not yet implemented}} +#pragma acc parallel loop independent pcopyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyout' not yet implemented}} +#pragma acc parallel loop independent present_or_copyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyin' not yet implemented}} +#pragma acc parallel loop independent copyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'pcopyin' not yet implemented}} +#pragma acc parallel loop independent pcopyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyin' not yet implemented}} +#pragma acc parallel loop independent present_or_copyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'create' not yet implemented}} +#pragma acc parallel loop independent create(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcreate' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcreate' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'pcreate' not yet implemented}} +#pragma acc parallel loop independent pcreate(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_create' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'present_or_create' not yet implemented}} +#pragma acc parallel loop independent present_or_create(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented}} +#pragma acc parallel loop independent reduction(+:Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented}} +#pragma acc parallel loop independent collapse(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'bind' not yet implemented}} +#pragma acc parallel loop independent bind(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'vector_length' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'vector_length' not yet implemented}} +#pragma acc parallel loop independent vector_length(1) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented}} +#pragma acc parallel loop independent num_gangs(1) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_workers' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented}} +#pragma acc parallel loop independent num_workers(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} +#pragma acc parallel loop independent device_num(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} +#pragma acc parallel loop independent default_async(1) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent device_type(*) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent dtype(*) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop independent async + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented}} +#pragma acc parallel loop independent tile(1+2, 1) + for(unsigned j = 0; j < 5; ++j) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} +#pragma acc parallel loop independent gang + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'wait' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc parallel loop independent wait + for(unsigned i = 0; i < 5; ++i); + + // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} +#pragma acc parallel loop finalize independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc parallel loop if_present independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} +#pragma acc parallel loop worker independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} +#pragma acc parallel loop vector independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} +#pragma acc parallel loop nohost independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop default(none) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop if(1) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop self independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} +#pragma acc parallel loop copy(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'pcopy' not yet implemented}} +#pragma acc parallel loop pcopy(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'present_or_copy' not yet implemented}} +#pragma acc parallel loop present_or_copy(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented}} +#pragma acc parallel loop use_device(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'attach' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'attach' not yet implemented}} +#pragma acc parallel loop attach(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'delete' not yet implemented}} +#pragma acc parallel loop delete(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'detach' not yet implemented}} +#pragma acc parallel loop detach(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc parallel loop device(VarPtr) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'deviceptr' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'deviceptr' not yet implemented}} +#pragma acc parallel loop deviceptr(VarPtr) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented}} +#pragma acc parallel loop device_resident(VarPtr) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop firstprivate(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc parallel loop host(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'link' not yet implemented}} +#pragma acc parallel loop link(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'no_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'no_create' not yet implemented}} +#pragma acc parallel loop no_create(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'present' not yet implemented}} +#pragma acc parallel loop present(Var) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop private(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyout' not yet implemented}} +#pragma acc parallel loop copyout(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TDOOexpected-error@+1{{OpenACC 'pcopyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'pcopyout' not yet implemented}} +#pragma acc parallel loop pcopyout(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyout' not yet implemented}} +#pragma acc parallel loop present_or_copyout(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TDOOexpected-error@+1{{OpenACC 'copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyin' not yet implemented}} +#pragma acc parallel loop copyin(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'pcopyin' not yet implemented}} +#pragma acc parallel loop pcopyin(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyin' not yet implemented}} +#pragma acc parallel loop present_or_copyin(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'create' not yet implemented}} +#pragma acc parallel loop create(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcreate' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcreate' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'pcreate' not yet implemented}} +#pragma acc parallel loop pcreate(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_create' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'present_or_create' not yet implemented}} +#pragma acc parallel loop present_or_create(Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented}} +#pragma acc parallel loop reduction(+:Var) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented}} +#pragma acc parallel loop collapse(1) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'bind' not yet implemented}} +#pragma acc parallel loop bind(Var) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'vector_length' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'vector_length' not yet implemented}} +#pragma acc parallel loop vector_length(1) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented}} +#pragma acc parallel loop num_gangs(1) independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_workers' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented}} +#pragma acc parallel loop num_workers(1) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} +#pragma acc parallel loop device_num(1) independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} +#pragma acc parallel loop default_async(1) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop device_type(*) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop dtype(*) independent + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop async independent + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented}} +#pragma acc parallel loop tile(1+2, 1) independent + for(unsigned j = 0; j < 5; ++j) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} +#pragma acc parallel loop gang independent + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'wait' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc parallel loop wait independent + for(unsigned i = 0; i < 5; ++i); + + // 'seq' cannot be combined with 'gang', 'worker' or 'vector' + // expected-error@+2{{OpenACC clause 'gang' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop seq gang + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'worker' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop seq worker + for(unsigned i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'vector' may not appear on the same construct as a 'seq' clause on a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop seq vector + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} +#pragma acc parallel loop seq finalize + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc parallel loop seq if_present + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} +#pragma acc parallel loop seq nohost + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq default(none) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq if(1) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq self + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} +#pragma acc parallel loop seq copy(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'pcopy' not yet implemented}} +#pragma acc parallel loop seq pcopy(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'present_or_copy' not yet implemented}} +#pragma acc parallel loop seq present_or_copy(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented}} +#pragma acc parallel loop seq use_device(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'attach' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'attach' not yet implemented}} +#pragma acc parallel loop seq attach(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'delete' not yet implemented}} +#pragma acc parallel loop seq delete(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'detach' not yet implemented}} +#pragma acc parallel loop seq detach(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc parallel loop seq device(VarPtr) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'deviceptr' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'deviceptr' not yet implemented}} +#pragma acc parallel loop seq deviceptr(VarPtr) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented}} +#pragma acc parallel loop seq device_resident(VarPtr) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq firstprivate(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc parallel loop seq host(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'link' not yet implemented}} +#pragma acc parallel loop seq link(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'no_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'no_create' not yet implemented}} +#pragma acc parallel loop seq no_create(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'present' not yet implemented}} +#pragma acc parallel loop seq present(Var) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq private(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyout' not yet implemented}} +#pragma acc parallel loop seq copyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'pcopyout' not yet implemented}} +#pragma acc parallel loop seq pcopyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyout' not yet implemented}} +#pragma acc parallel loop seq present_or_copyout(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyin' not yet implemented}} +#pragma acc parallel loop seq copyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'pcopyin' not yet implemented}} +#pragma acc parallel loop seq pcopyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyin' not yet implemented}} +#pragma acc parallel loop seq present_or_copyin(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'create' not yet implemented}} +#pragma acc parallel loop seq create(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcreate' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcreate' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'pcreate' not yet implemented}} +#pragma acc parallel loop seq pcreate(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_create' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'present_or_create' not yet implemented}} +#pragma acc parallel loop seq present_or_create(Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented}} +#pragma acc parallel loop seq reduction(+:Var) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented}} +#pragma acc parallel loop seq collapse(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'bind' not yet implemented}} +#pragma acc parallel loop seq bind(Var) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'vector_length' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'vector_length' not yet implemented}} +#pragma acc parallel loop seq vector_length(1) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented}} +#pragma acc parallel loop seq num_gangs(1) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_workers' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented}} +#pragma acc parallel loop seq num_workers(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} +#pragma acc parallel loop seq device_num(1) + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} +#pragma acc parallel loop seq default_async(1) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq device_type(*) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq dtype(*) + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop seq async + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented}} +#pragma acc parallel loop seq tile(1+2, 1) + for(;;) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'wait' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc parallel loop seq wait + for(unsigned i = 0; i < 5; ++i); + + // TODOexpected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'gang' clause on a 'parallel loop' construct}} + // TODOexpected-note@+1{{previous clause is here}} + // expected-warning@+1{{OpenACC clause 'gang' not yet implemented}} +#pragma acc parallel loop gang seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'worker' clause on a 'parallel loop' construct}} + // TODOexpected-note@+1{{previous clause is here}} + // expected-warning@+1{{OpenACC clause 'worker' not yet implemented}} +#pragma acc parallel loop worker seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'vector' clause on a 'parallel loop' construct}} + // TODOexpected-note@+1{{previous clause is here}} + // expected-warning@+1{{OpenACC clause 'vector' not yet implemented}} +#pragma acc parallel loop vector seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}} +#pragma acc parallel loop finalize seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc parallel loop if_present seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}} +#pragma acc parallel loop nohost seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop default(none) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop if(1) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop self seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} +#pragma acc parallel loop copy(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'pcopy' not yet implemented}} +#pragma acc parallel loop pcopy(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copy' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copy' is a deprecated clause name and is now an alias for 'copy'}} + // expected-warning@+1{{OpenACC clause 'present_or_copy' not yet implemented}} +#pragma acc parallel loop present_or_copy(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'use_device' not yet implemented}} +#pragma acc parallel loop use_device(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'attach' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'attach' not yet implemented}} +#pragma acc parallel loop attach(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'delete' not yet implemented}} +#pragma acc parallel loop delete(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'detach' not yet implemented}} +#pragma acc parallel loop detach(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc parallel loop device(VarPtr) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'deviceptr' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'deviceptr' not yet implemented}} +#pragma acc parallel loop deviceptr(VarPtr) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_resident' not yet implemented}} +#pragma acc parallel loop device_resident(VarPtr) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop firstprivate(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc parallel loop host(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'link' not yet implemented}} +#pragma acc parallel loop link(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'no_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'no_create' not yet implemented}} +#pragma acc parallel loop no_create(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'present' not yet implemented}} +#pragma acc parallel loop present(Var) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop private(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyout' not yet implemented}} +#pragma acc parallel loop copyout(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'pcopyout' not yet implemented}} +#pragma acc parallel loop pcopyout(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyout' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyout' is a deprecated clause name and is now an alias for 'copyout'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyout' not yet implemented}} +#pragma acc parallel loop present_or_copyout(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'copyin' not yet implemented}} +#pragma acc parallel loop copyin(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcopyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcopyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'pcopyin' not yet implemented}} +#pragma acc parallel loop pcopyin(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_copyin' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_copyin' is a deprecated clause name and is now an alias for 'copyin'}} + // expected-warning@+1{{OpenACC clause 'present_or_copyin' not yet implemented}} +#pragma acc parallel loop present_or_copyin(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'create' not yet implemented}} +#pragma acc parallel loop create(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'pcreate' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'pcreate' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'pcreate' not yet implemented}} +#pragma acc parallel loop pcreate(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'present_or_create' clause is not valid on 'parallel loop' directive}} + // expected-warning@+2{{OpenACC clause name 'present_or_create' is a deprecated clause name and is now an alias for 'create'}} + // expected-warning@+1{{OpenACC clause 'present_or_create' not yet implemented}} +#pragma acc parallel loop present_or_create(Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented}} +#pragma acc parallel loop reduction(+:Var) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented}} +#pragma acc parallel loop collapse(1) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'bind' not yet implemented}} +#pragma acc parallel loop bind(Var) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'vector_length' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'vector_length' not yet implemented}} +#pragma acc parallel loop vector_length(1) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_gangs' not yet implemented}} +#pragma acc parallel loop num_gangs(1) seq + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'num_workers' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented}} +#pragma acc parallel loop num_workers(1) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'device_num' not yet implemented}} +#pragma acc parallel loop device_num(1) seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented}} +#pragma acc parallel loop default_async(1) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop device_type(*) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop dtype(*) seq + for(unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop async seq + for(unsigned i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented}} +#pragma acc parallel loop tile(1+2, 1) seq + for(;;) + for(unsigned i = 0; i < 5; ++i); + // TODOexpected-error@+1{{OpenACC 'wait' clause is not valid on 'parallel loop' directive}} + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc parallel loop wait seq + for(unsigned i = 0; i < 5; ++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-default-ast.cpp b/clang/test/SemaOpenACC/combined-construct-default-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ff24b32afe7b91a6048851d963548dfeca937d7 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-default-ast.cpp @@ -0,0 +1,76 @@ + +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER +void NormalFunc() { + // CHECK-LABEL: NormalFunc + // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}}parallel loop + // CHECK-NEXT: default(none) +#pragma acc parallel loop default(none) + for (unsigned I = 0; I < 5; ++I) { +#pragma acc kernels loop + for (unsigned J = 0; J < 5; ++J) { + } + // CHECK: OpenACCCombinedConstruct {{.*}}kernels loop + // CHECK: OpenACCCombinedConstruct {{.*}}serial loop + // CHECK-NEXT: default(present) +#pragma acc serial loop default(present) + for (unsigned J = 0; J < 5; ++J) { + } + } +} +template +void TemplFunc() { +#pragma acc parallel loop default(none) + for (unsigned i = 0; i < 5; ++i) { + typename T::type I; + } + +#pragma acc serial loop default(present) + for (unsigned i = 0; i < 5; ++i) { + typename T::type I; + } + + // CHECK-LABEL: FunctionTemplateDecl {{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + + // Template Pattern: + // CHECK-NEXT: FunctionDecl + // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}}parallel loop + // CHECK-NEXT: default(none) + // CHECK: VarDecl{{.*}} I 'typename T::type' + + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}}serial loop + // CHECK-NEXT: default(present) + // CHECK: VarDecl{{.*}} I 'typename T::type' + + // Check instantiation. + // CHECK-LABEL: FunctionDecl{{.*}} used TemplFunc 'void ()' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'S' + // CHECK-NEXT: RecordType + // CHECK-NEXT: CXXRecord + // CHECK-NEXT: CompoundStmt + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}}parallel loop + // CHECK-NEXT: default(none) + // CHECK: VarDecl{{.*}} I 'typename S::type':'int' + // CHECK-NEXT: OpenACCCombinedConstruct {{.*}}serial loop + // CHECK-NEXT: default(present) + // CHECK: VarDecl{{.*}} I 'typename S::type':'int' + +} +struct S { + using type = int; +}; + +void use() { + TemplFunc(); +} + +#endif diff --git a/clang/test/SemaOpenACC/combined-construct-default-clause.c b/clang/test/SemaOpenACC/combined-construct-default-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..646942ec700133744ce414fe7f94c956c93ea2dc --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-default-clause.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void SingleOnly() { + #pragma acc parallel loop default(none) + for(int i = 5; i < 10;++i); + + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'serial loop' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc serial loop default(present) self default(none) + for(int i = 5; i < 10;++i); + + int i; + + // expected-warning@+4{{OpenACC clause 'copy' not yet implemented}} + // expected-warning@+3{{OpenACC clause 'present' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'kernels loop' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc kernels loop self default(present) present(i) default(none) copy(i) + for(int i = 5; i < 10;++i); + + // expected-warning@+3{{OpenACC clause 'copy' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'parallel loop' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc parallel loop self default(present) private(i) default(none) copy(i) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{expected '('}} + #pragma acc serial loop self default private(i) default(none) if(i) + for(int i = 0; i < 5; ++i); + + #pragma acc kernels loop default(none) + for(int i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'data' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} + #pragma acc data default(none) + while(0); + + // expected-error@+1{{OpenACC 'default' clause is not valid on 'loop' directive}} + #pragma acc loop default(none) + for(int i = 5; i < 10;++i); + + // expected-warning@+2{{OpenACC construct 'wait' not yet implemented}} + // expected-error@+1{{OpenACC 'default' clause is not valid on 'wait' directive}} + #pragma acc wait default(none) + while(0); + + // expected-error@+1{{OpenACC 'default' clause is not valid on 'loop' directive}} +#pragma acc loop default(present) + for(int i = 5; i < 10;++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-default-clause.cpp b/clang/test/SemaOpenACC/combined-construct-default-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70c9a7cb47813345864bf5c15524bcf492ffe960 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-default-clause.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void SingleOnly() { + #pragma acc parallel loop default(none) + for (unsigned I = 0; I < 5; ++I); + + int i; + + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'parallel loop' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc parallel loop default(present) async default(none) + for (unsigned I = 0; I < 5; ++I); + + // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'serial loop' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc serial loop async default(present) copy(i) default(none) self + for (unsigned I = 0; I < 5; ++I); + + // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'kernels loop' directive}} + // expected-note@+1{{previous clause is here}} + #pragma acc kernels loop async default(present) copy(i) default(none) self + for (unsigned I = 0; I < 5; ++I); + + // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}} + // expected-error@+1{{expected '('}} + #pragma acc parallel loop async default(none) copy(i) default self + for (unsigned I = 0; I < 5; ++I); +} + +void Instantiate() { + SingleOnly(); +} diff --git a/clang/test/SemaOpenACC/combined-construct-device_type-ast.cpp b/clang/test/SemaOpenACC/combined-construct-device_type-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abc65dfc9e5227a99122ed5dee908a871473c65f --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-device_type-ast.cpp @@ -0,0 +1,178 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER + +struct SomeS{}; +void NormalUses() { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK-NEXT: CompoundStmt + + SomeS SomeImpl; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} SomeImpl 'SomeS' + // CHECK-NEXT: CXXConstructExpr + bool SomeVar; + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} SomeVar 'bool' + +#pragma acc parallel loop device_type(SomeS) dtype(SomeImpl) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: device_type(SomeS) + // CHECK-NEXT: dtype(SomeImpl) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +#pragma acc serial loop device_type(SomeVar) dtype(int) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: device_type(SomeVar) + // CHECK-NEXT: dtype(int) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +#pragma acc kernels loop device_type(private) dtype(struct) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: device_type(private) + // CHECK-NEXT: dtype(struct) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +#pragma acc parallel loop device_type(private) dtype(class) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: device_type(private) + // CHECK-NEXT: dtype(class) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +#pragma acc serial loop device_type(float) dtype(*) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: device_type(float) + // CHECK-NEXT: dtype(*) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +#pragma acc kernels loop device_type(float, int) dtype(*) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: device_type(float, int) + // CHECK-NEXT: dtype(*) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +} + +template +void TemplUses() { + // CHECK-NEXT: FunctionTemplateDecl{{.*}}TemplUses + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}T + // CHECK-NEXT: FunctionDecl{{.*}}TemplUses + // CHECK-NEXT: CompoundStmt +#pragma acc parallel loop device_type(T) dtype(T) + for(int i = 0; i < 5; ++i){} + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: dtype(T) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt + + + // Instantiations + // CHECK-NEXT: FunctionDecl{{.*}} TemplUses 'void ()' implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: device_type(T) + // CHECK-NEXT: dtype(T) + // CHECK-NEXT: ForStmt + // CHECK-NEXT: DeclStmt + // CHECK-NEXT: VarDecl{{.*}} i 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0 + // CHECK-NEXT: <<>> + // CHECK-NEXT: BinaryOperator{{.*}}'<' + // CHECK-NEXT: ImplicitCastExpr + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5 + // CHECK-NEXT: UnaryOperator{{.*}}++ + // CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int' + // CHECK-NEXT: CompoundStmt +} + +void Inst() { + TemplUses(); +} + +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/combined-construct-device_type-clause.c b/clang/test/SemaOpenACC/combined-construct-device_type-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..9b7a3ec6b0adae979f13ee4803f960c60c4a9953 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-device_type-clause.c @@ -0,0 +1,224 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +#define MACRO +FOO + +void uses() { + typedef struct S{} STy; + STy SImpl; + +#pragma acc parallel loop device_type(I) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop device_type(S) dtype(STy) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop dtype(SImpl) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop dtype(int) device_type(*) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop dtype(true) device_type(false) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{expected identifier}} +#pragma acc kernels loop dtype(int, *) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop device_type(I, int) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{expected ','}} + // expected-error@+1{{expected identifier}} +#pragma acc kernels loop dtype(int{}) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{expected identifier}} +#pragma acc kernels loop dtype(5) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{expected identifier}} +#pragma acc kernels loop dtype(MACRO) + for(int i = 0; i < 5; ++i); + + // Compute constructs allow 'async', 'wait', num_gangs', 'num_workers', + // 'vector_length' after 'device_type', loop allows 'collapse', 'gang', + // 'worker', 'vector', 'seq', 'independent', 'auto', and 'tile' after + // 'device_type'. + + //expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}} +#pragma acc parallel loop device_type(*) vector + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{OpenACC clause 'finalize' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) finalize + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) if_present + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop device_type(*) seq + for(int i = 0; i < 5; ++i); +#pragma acc serial loop device_type(*) independent + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop device_type(*) auto + for(int i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'worker' not yet implemented, clause ignored}} +#pragma acc parallel loop device_type(*) worker + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) nohost + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'default' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) default(none) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) if(1) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'self' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) self + for(int i = 0; i < 5; ++i); + + int Var; + int *VarPtr; + // expected-error@+2{{OpenACC clause 'copy' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) copy(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'pcopy' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) pcopy(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'present_or_copy' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) present_or_copy(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'use_device' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) use_device(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'attach' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) attach(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'delete' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) delete(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'detach' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) detach(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'device' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) device(VarPtr) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'deviceptr' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) deviceptr(VarPtr) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'device_resident' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) device_resident(VarPtr) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'firstprivate' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) firstprivate(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'host' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) host(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'link' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) link(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'no_create' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) no_create(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'present' may not follow a 'device_type' clause in a 'kernels loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop device_type(*) present(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'private' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) private(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'copyout' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) copyout(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'pcopyout' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) pcopyout(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'present_or_copyout' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) present_or_copyout(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'copyin' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) copyin(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'pcopyin' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) pcopyin(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'present_or_copyin' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) present_or_copyin(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'create' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) create(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'pcreate' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) pcreate(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'present_or_create' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) present_or_create(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'reduction' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) reduction(+:Var) + for(int i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'collapse' not yet implemented, clause ignored}} +#pragma acc serial loop device_type(*) collapse(1) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'bind' may not follow a 'device_type' clause in a 'parallel loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop device_type(*) bind(Var) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC 'vector_length' clause is not valid on 'serial loop' directive}} +#pragma acc serial loop device_type(*) vector_length(1) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial loop' directive}} +#pragma acc serial loop device_type(*) num_gangs(1) + for(int i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'num_workers' not yet implemented, clause ignored}} +#pragma acc parallel loop device_type(*) num_workers(1) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) device_num(1) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a 'serial loop' construct}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop device_type(*) default_async(1) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop device_type(*) async + for(int i = 0; i < 5; ++i); + + // expected-warning@+1{{OpenACC clause 'tile' not yet implemented, clause ignored}} +#pragma acc serial loop device_type(*) tile(*, 1) + for(int j = 0; j < 5; ++j) + for(int i = 0; i < 5; ++i); + + // expected-warning@+1{{OpenACC clause 'gang' not yet implemented, clause ignored}} +#pragma acc serial loop dtype(*) gang + for(int i = 0; i < 5; ++i); + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented, clause ignored}} +#pragma acc parallel loop device_type(*) wait + for(int i = 0; i < 5; ++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-device_type-clause.cpp b/clang/test/SemaOpenACC/combined-construct-device_type-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b46709aa8d4ce3f8c92a42ca08195507132faa39 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-device_type-clause.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +template +void TemplUses() { +#pragma acc parallel loop device_type(I) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop dtype(*) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop device_type(class) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop device_type(private) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop device_type(bool) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop dtype(true) device_type(false) + for(int i = 0; i < 5; ++i); + // expected-error@+2{{expected ','}} + // expected-error@+1{{expected identifier}} +#pragma acc kernels loop device_type(T::value) + for(int i = 0; i < 5; ++i); +} + +void Inst() { + TemplUses(); // #INST +} diff --git a/clang/test/SemaOpenACC/combined-construct-firstprivate-clause.c b/clang/test/SemaOpenACC/combined-construct-firstprivate-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..107874b6d3b5aa04c4f9780e1b3c63451c578410 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-firstprivate-clause.c @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +typedef struct IsComplete { + struct S { int A; } CompositeMember; + int ScalarMember; + float ArrayMember[5]; + void *PointerMember; +} Complete; +void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete CompositeParam) { + int LocalInt; + short *LocalPointer; + float LocalArray[5]; + Complete LocalComposite; + // Check Appertainment: +#pragma acc parallel loop firstprivate(LocalInt) + for (int i = 5; i < 10; ++i); +#pragma acc serial loop firstprivate(LocalInt) + for (int i = 5; i < 10; ++i); + // expected-error@+1{{OpenACC 'firstprivate' clause is not valid on 'kernels loop' directive}} +#pragma acc kernels loop firstprivate(LocalInt) + for (int i = 5; i < 10; ++i); + + // Valid cases: +#pragma acc parallel loop firstprivate(LocalInt, LocalPointer, LocalArray) + for (int i = 5; i < 10; ++i); +#pragma acc serial loop firstprivate(LocalArray[2:1]) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop firstprivate(LocalComposite.ScalarMember, LocalComposite.ScalarMember) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop firstprivate(1 + IntParam) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop firstprivate(+IntParam) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} +#pragma acc parallel loop firstprivate(PointerParam[2:]) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} +#pragma acc serial loop firstprivate(ArrayParam[2:5]) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop firstprivate((float*)ArrayParam[2:5]) + for (int i = 5; i < 10; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop firstprivate((float)ArrayParam[2]) + for (int i = 5; i < 10; ++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-firstprivate-clause.cpp b/clang/test/SemaOpenACC/combined-construct-firstprivate-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b888ae4c6b58e5f57218e058732bcf8b60866b6 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-firstprivate-clause.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +enum SomeE{}; +typedef struct IsComplete { + struct S { int A; } CompositeMember; + int ScalarMember; + float ArrayMember[5]; + SomeE EnumMember; + char *PointerMember; +} Complete; + +void uses(int IntParam, char *PointerParam, float ArrayParam[5], Complete CompositeParam, int &IntParamRef) { + int LocalInt; + char *LocalPointer; + float LocalArray[5]; + // Check Appertainment: +#pragma acc parallel loop firstprivate(LocalInt) + for (int i = 5; i < 10; ++i); +#pragma acc serial loop firstprivate(LocalInt) + for (int i = 5; i < 10; ++i); + // expected-error@+1{{OpenACC 'firstprivate' clause is not valid on 'kernels loop' directive}} +#pragma acc kernels loop firstprivate(LocalInt) + for (int i = 5; i < 10; ++i); + + // Valid cases: +#pragma acc parallel loop firstprivate(LocalInt, LocalPointer, LocalArray) + for (int i = 5; i < 10; ++i); +#pragma acc serial loop firstprivate(LocalArray[2:1]) + for (int i = 5; i < 10; ++i); + + Complete LocalComposite2; +#pragma acc parallel loop firstprivate(LocalComposite2.ScalarMember, LocalComposite2.ScalarMember) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop firstprivate(1 + IntParam) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop firstprivate(+IntParam) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} +#pragma acc parallel loop firstprivate(PointerParam[2:]) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} +#pragma acc parallel loop firstprivate(ArrayParam[2:5]) + for (int i = 5; i < 10; ++i); + + // expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop firstprivate((float*)ArrayParam[2:5]) + for (int i = 5; i < 10; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop firstprivate((float)ArrayParam[2]) + for (int i = 5; i < 10; ++i); +} + +template +void TemplUses(T t, T (&arrayT)[I], V TemplComp) { + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop firstprivate(+t) + for (int i = 5; i < 10; ++i); + + // NTTP's are only valid if it is a reference to something. + // expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} + // expected-note@#TEMPL_USES_INST{{in instantiation of}} +#pragma acc parallel loop firstprivate(I) + for (int i = 5; i < 10; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop firstprivate(t, I) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop firstprivate(arrayT) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop firstprivate(TemplComp) + for (int i = 5; i < 10; ++i); + +#pragma acc parallel loop firstprivate(TemplComp.PointerMember[5]) + for (int i = 5; i < 10; ++i); + int *Pointer; +#pragma acc serial loop firstprivate(Pointer[:I]) + for (int i = 5; i < 10; ++i); +#pragma acc parallel loop firstprivate(Pointer[:t]) + for (int i = 5; i < 10; ++i); + // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} +#pragma acc parallel loop firstprivate(Pointer[1:]) + for (int i = 5; i < 10; ++i); +} + +template +void NTTP() { + // NTTP's are only valid if it is a reference to something. + // expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} + // expected-note@#NTTP_INST{{in instantiation of}} +#pragma acc parallel loop firstprivate(I) + for (int i = 5; i < 10; ++i); + +#pragma acc serial loop firstprivate(NTTP_REF) + for (int i = 5; i < 10; ++i); +} + +void Inst() { + static constexpr int NTTP_REFed = 1; + int i; + int Arr[5]; + Complete C; + TemplUses(i, Arr, C); // #TEMPL_USES_INST + NTTP<5, NTTP_REFed>(); // #NTTP_INST +} diff --git a/clang/test/SemaOpenACC/combined-construct-if-ast.cpp b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0796409d942d798e18b7dd40f96fa4e4d59dc60 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-if-ast.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER +void NormalFunc(int j, float f) { + // CHECK: FunctionDecl{{.*}}NormalFunc + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: CompoundStmt +#pragma acc kernels loop if( j < f) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}} 'int' lvalue ParmVar{{.*}} 'j' 'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'float' lvalue ParmVar{{.*}} 'f' 'float' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} + +template +void TemplFunc() { + // CHECK: FunctionTemplateDecl{{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + + // Match the prototype: + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop if(T::SomeFloat < typename T::IntTy{}) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} '' '<' + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename T::IntTy' 'typename T::IntTy' + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop if(typename T::IntTy{}) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: CXXUnresolvedConstructExpr{{.*}} 'typename T::IntTy' 'typename T::IntTy' + // CHECK-NEXT: InitListExpr{{.*}} 'void' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop if(T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop if(T::BC) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // Match the instantiation: + // CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'InstTy' + // CHECK-NEXT: RecordType{{.*}} 'InstTy' + // CHECK-NEXT: CXXRecord{{.*}} 'InstTy' + // CHECK-NEXT: CompoundStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: BinaryOperator{{.*}} 'bool' '<' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float' + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy + // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: CXXFunctionalCastExpr{{.*}}'typename InstTy::IntTy':'int' functional cast to typename struct InstTy::IntTy + // CHECK-NEXT: InitListExpr {{.*}}'typename InstTy::IntTy':'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'bool' + // CHECK-NEXT: CXXMemberCallExpr{{.*}} 'bool' + // CHECK-NEXT: MemberExpr{{.*}} .operator bool + // CHECK-NEXT: DeclRefExpr{{.*}} 'const BoolConversion' lvalue Var{{.*}} 'BC' 'const BoolConversion' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} + +struct BoolConversion{ operator bool() const;}; +struct InstTy { + using IntTy = int; + static constexpr float SomeFloat = 5.0; + static constexpr BoolConversion BC; +}; + +void Instantiate() { + TemplFunc(); +} +#endif diff --git a/clang/test/SemaOpenACC/combined-construct-if-clause.c b/clang/test/SemaOpenACC/combined-construct-if-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..563f1cd25377bdff121d831189e41cb8b3519997 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-if-clause.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void BoolExpr(int *I, float *F) { + + typedef struct {} SomeStruct; + int Array[5]; + + struct C{}; + // expected-error@+1{{expected expression}} +#pragma acc parallel loop if (struct C f()) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial loop if (SomeStruct) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial loop if (SomeStruct()) + for (unsigned i = 0; i < 5; ++i); + + SomeStruct S; + // expected-error@+1{{statement requires expression of scalar type ('SomeStruct' invalid)}} +#pragma acc serial loop if (S) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+1{{address of array 'Array' will always evaluate to 'true'}} +#pragma acc kernels loop if (Array) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+4{{incompatible pointer types assigning to 'int *' from 'float *'}} + // expected-warning@+3{{using the result of an assignment as a condition without parentheses}} + // expected-note@+2{{place parentheses around the assignment to silence this warning}} + // expected-note@+1{{use '==' to turn this assignment into an equality comparison}} +#pragma acc kernels loop if (I = F) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop if (I) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc serial loop if (F) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop if (*I < *F) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'data' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc data if (*I < *F) + for (unsigned i = 0; i < 5; ++i); +#pragma acc parallel loop if (*I < *F) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop if (*I < *F) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop if (*I < *F) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC 'if' clause is not valid on 'loop' directive}} +#pragma acc loop if(I) + for(int i = 5; i < 10;++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-if-clause.cpp b/clang/test/SemaOpenACC/combined-construct-if-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf1bdadd4c8921c8a9015fbd398651bec496913f --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-if-clause.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NoBoolConversion{}; +struct BoolConversion{ + operator bool(); +}; + +template +void BoolExpr() { + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel loop if (NoBoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+2{{no member named 'NotValid' in 'NoBoolConversion'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc serial loop if (T::NotValid) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop if (BoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc serial loop if (T{}) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop if (U{}) + for (unsigned i = 0; i < 5; ++i); +} + +void Instantiate() { + BoolExpr(); // #INST +} diff --git a/clang/test/SemaOpenACC/combined-construct-private-clause.c b/clang/test/SemaOpenACC/combined-construct-private-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..1cd30db8f4aa792c9326de3302b6bc26f29f4248 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-private-clause.c @@ -0,0 +1,128 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct Incomplete; +enum SomeE{ A }; +typedef struct IsComplete { + struct S { int A; } CompositeMember; + int ScalarMember; + float ArrayMember[5]; + enum SomeE EnumMember; + void *PointerMember; +} Complete; + +int GlobalInt; +float GlobalArray[5]; +short *GlobalPointer; +Complete GlobalComposite; + +void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete CompositeParam) { + int LocalInt; + short *LocalPointer; + float LocalArray[5]; + Complete LocalComposite; + + // Valid cases: +#pragma acc parallel loop private(LocalInt, LocalPointer, LocalArray) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalArray) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalArray[:]) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(LocalArray[:5]) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalArray[2:]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalArray[2:1]) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(LocalArray[2]) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalComposite) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalComposite.EnumMember) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(LocalComposite.ScalarMember) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalComposite.ArrayMember) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(LocalComposite.ArrayMember[5]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalComposite.PointerMember) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(GlobalInt, GlobalArray, GlobalPointer, GlobalComposite) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(GlobalArray[2], GlobalPointer[2], GlobalComposite.CompositeMember.A) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalComposite, GlobalComposite) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(IntParam, PointerParam, ArrayParam, CompositeParam) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(PointerParam[IntParam], ArrayParam[IntParam], CompositeParam.CompositeMember.A) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop private(LocalArray) private(LocalArray[2]) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop private(LocalArray, LocalArray[2]) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop private(LocalComposite, LocalComposite.ScalarMember) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop private(LocalComposite.CompositeMember.A, LocalComposite.ScalarMember) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop private(LocalComposite.CompositeMember.A) private(LocalComposite.ScalarMember) + for(int i = 0; i < 5; ++i); + + Complete LocalComposite2; +#pragma acc kernels loop private(LocalComposite2.ScalarMember, LocalComposite2.ScalarMember) + for(int i = 0; i < 5; ++i); + + // Invalid cases, arbitrary expressions. + struct Incomplete *I; + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop private(*I) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop private(GlobalInt + IntParam) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc kernels loop private(+GlobalInt) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} +#pragma acc parallel loop private(PointerParam[:]) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(PointerParam[:5]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(PointerParam[:IntParam]) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} +#pragma acc parallel loop private(PointerParam[2:]) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(PointerParam[2:5]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(PointerParam[2]) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(ArrayParam[:]) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(ArrayParam[:5]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(ArrayParam[:IntParam]) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(ArrayParam[2:]) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} +#pragma acc serial loop private(ArrayParam[2:5]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(ArrayParam[2]) + for(int i = 0; i < 5; ++i); + + // expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop private((float*)ArrayParam[2:5]) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc kernels loop private((float)ArrayParam[2]) + for(int i = 0; i < 5; ++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-private-clause.cpp b/clang/test/SemaOpenACC/combined-construct-private-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d94c336c21d97a09684a7a9a7fd3673ce4e4686c --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-private-clause.cpp @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct Incomplete; +enum SomeE{}; +typedef struct IsComplete { + struct S { int A; } CompositeMember; + int ScalarMember; + float ArrayMember[5]; + SomeE EnumMember; + char *PointerMember; +} Complete; + +int GlobalInt; +float GlobalArray[5]; +char *GlobalPointer; +Complete GlobalComposite; + +void uses(int IntParam, char *PointerParam, float ArrayParam[5], Complete CompositeParam, int &IntParamRef) { + int LocalInt; + char *LocalPointer; + float LocalArray[5]; + Complete LocalComposite; + + // Valid cases: +#pragma acc parallel loop private(LocalInt, LocalPointer, LocalArray) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalArray) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalArray[2]) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(LocalComposite) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalComposite.EnumMember) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalComposite.ScalarMember) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(LocalComposite.ArrayMember) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(LocalComposite.ArrayMember[5]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalComposite.PointerMember) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(GlobalInt, GlobalArray, GlobalPointer, GlobalComposite) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(GlobalArray[2], GlobalPointer[2], GlobalComposite.CompositeMember.A) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(LocalComposite, GlobalComposite) + for(int i = 0; i < 5; ++i); +#pragma acc parallel loop private(IntParam, PointerParam, ArrayParam, CompositeParam) private(IntParamRef) + for(int i = 0; i < 5; ++i); +#pragma acc serial loop private(PointerParam[IntParam], ArrayParam[IntParam], CompositeParam.CompositeMember.A) + for(int i = 0; i < 5; ++i); + + + // Invalid cases, arbitrary expressions. + Incomplete *I; + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc kernels loop private(*I) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop private(GlobalInt + IntParam) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc serial loop private(+GlobalInt) + for(int i = 0; i < 5; ++i); +} + +template +void TemplUses(T t, T (&arrayT)[I], V TemplComp) { + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc kernels loop private(+t) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc parallel loop private(+I) + for(int i = 0; i < 5; ++i); + + // NTTP's are only valid if it is a reference to something. + // expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} + // expected-note@#TEMPL_USES_INST{{in instantiation of}} +#pragma acc serial loop private(I) + for(int i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} +#pragma acc kernels loop private(t, I) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop private(arrayT) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop private(TemplComp) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop private(TemplComp.PointerMember[5]) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop private(TemplComp.PointerMember[5]) private(TemplComp) + for(int i = 0; i < 5; ++i); + + int *Pointer; +#pragma acc serial loop private(Pointer[:I]) + for(int i = 0; i < 5; ++i); +#pragma acc kernels loop private(Pointer[:t]) + for(int i = 0; i < 5; ++i); + // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} +#pragma acc parallel loop private(Pointer[1:]) + for(int i = 0; i < 5; ++i); +} + +template +void NTTP() { + // NTTP's are only valid if it is a reference to something. + // expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} + // expected-note@#NTTP_INST{{in instantiation of}} +#pragma acc serial loop private(I) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop private(NTTP_REF) + for(int i = 0; i < 5; ++i); +} + +struct S { + int ThisMember; + int ThisMemberArray[5]; + + void foo(); +}; + +void S::foo() { +#pragma acc parallel loop private(ThisMember, this->ThisMemberArray[1]) + for(int i = 0; i < 5; ++i); + +#pragma acc serial loop private(ThisMemberArray[1:2]) + for(int i = 0; i < 5; ++i); + +#pragma acc kernels loop private(this) + for(int i = 0; i < 5; ++i); + +#pragma acc parallel loop private(ThisMember, this->ThisMember) + for(int i = 0; i < 5; ++i); +} + +void Inst() { + static constexpr int NTTP_REFed = 1; + int i; + int Arr[5]; + Complete C; + TemplUses(i, Arr, C); // #TEMPL_USES_INST + NTTP<5, NTTP_REFed>(); // #NTTP_INST +} diff --git a/clang/test/SemaOpenACC/combined-construct-private-firstprivate-ast.cpp b/clang/test/SemaOpenACC/combined-construct-private-firstprivate-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03c258aca4f6aa14b3d27e9acabd702d2b192747 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-private-firstprivate-ast.cpp @@ -0,0 +1,226 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s +#ifndef PCH_HELPER +#define PCH_HELPER + +int Global; +short GlobalArray[5]; + +void NormalUses(float *PointerParam) { + // CHECK: FunctionDecl{{.*}}NormalUses + // CHECK: ParmVarDecl + // CHECK-NEXT: CompoundStmt + +#pragma acc parallel loop private(Global, GlobalArray[2]) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ArraySubscriptExpr{{.*}}'short' lvalue + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'short *' + // CHECK-NEXT: DeclRefExpr{{.*}}'short[5]' lvalue Var{{.*}}'GlobalArray' 'short[5]' + // CHECK-NEXT: IntegerLiteral{{.*}} 'int' 2 + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop private(GlobalArray, PointerParam[Global]) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'short[5]' lvalue Var{{.*}}'GlobalArray' 'short[5]' + // CHECK-NEXT: ArraySubscriptExpr{{.*}}'float' lvalue + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float *' + // CHECK-NEXT: DeclRefExpr{{.*}}'float *' lvalue ParmVar{{.*}}'PointerParam' 'float *' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop firstprivate(GlobalArray, PointerParam[Global]) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: firstprivate clause + // CHECK-NEXT: DeclRefExpr{{.*}}'short[5]' lvalue Var{{.*}}'GlobalArray' 'short[5]' + // CHECK-NEXT: ArraySubscriptExpr{{.*}}'float' lvalue + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float *' + // CHECK-NEXT: DeclRefExpr{{.*}}'float *' lvalue ParmVar{{.*}}'PointerParam' 'float *' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop firstprivate(GlobalArray, PointerParam[Global : Global]) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: firstprivate clause + // CHECK-NEXT: DeclRefExpr{{.*}}'short[5]' lvalue Var{{.*}}'GlobalArray' 'short[5]' + // CHECK-NEXT: ArraySectionExpr + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'float *' + // CHECK-NEXT: DeclRefExpr{{.*}}'float *' lvalue ParmVar{{.*}} 'PointerParam' 'float *' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} +template +void TemplUses(T t, U u, T*PointerParam) { + + // CHECK: FunctionTemplateDecl{{.*}}TemplUses + // CHECK-NEXT: NonTypeTemplateParmDecl {{.*}}referenced 'auto &' depth 0 index 0 NTTP + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}typename depth 0 index 1 T + // CHECK-NEXT: TemplateTypeParmDecl{{.*}}typename depth 0 index 2 U + // CHECK-NEXT: FunctionDecl{{.*}} TemplUses 'void (T, U, T *)' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced t 'T' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced u 'U' + // CHECK-NEXT: ParmVarDecl{{.*}} referenced PointerParam 'T *' + // CHECK-NEXT: CompoundStmt +#pragma acc serial loop private(GlobalArray, PointerParam[Global]) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'short[5]' lvalue Var{{.*}}'GlobalArray' 'short[5]' + // CHECK-NEXT: ArraySubscriptExpr{{.*}}'T' lvalue + // CHECK-NEXT: DeclRefExpr{{.*}}'T *' lvalue ParmVar{{.*}}'PointerParam' 'T *' + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop private(t, u) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'T' lvalue ParmVar{{.*}} 't' 'T' + // CHECK-NEXT: DeclRefExpr{{.*}}'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop firstprivate(t, u) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: firstprivate clause + // CHECK-NEXT: DeclRefExpr{{.*}}'T' lvalue ParmVar{{.*}} 't' 'T' + // CHECK-NEXT: DeclRefExpr{{.*}}'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop private(t) private(u) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'T' lvalue ParmVar{{.*}} 't' 'T' + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop private(t) private(NTTP, u) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'T' lvalue ParmVar{{.*}} 't' 'T' + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'auto' lvalue NonTypeTemplateParm{{.*}} 'NTTP' 'auto &' + // CHECK-NEXT: DeclRefExpr{{.*}}'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop private(t) firstprivate(NTTP, u) + for (int i = 5; i < 10; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'T' lvalue ParmVar{{.*}} 't' 'T' + // CHECK-NEXT: firstprivate clause + // CHECK-NEXT: DeclRefExpr{{.*}}'auto' lvalue NonTypeTemplateParm{{.*}} 'NTTP' 'auto &' + // CHECK-NEXT: DeclRefExpr{{.*}}'U' lvalue ParmVar{{.*}} 'u' 'U' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // Check the instantiated versions of the above. + // CHECK-NEXT: FunctionDecl{{.*}} used TemplUses 'void (int, int *, int *)' implicit_instantiation + // CHECK-NEXT: TemplateArgument decl + // CHECK-NEXT: Var{{.*}} 'CEVar' 'const unsigned int' + // CHECK-NEXT: TemplateArgument type 'int' + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: TemplateArgument type 'int[1]' + // CHECK-NEXT: ConstantArrayType{{.*}} 'int[1]'{{.*}} 1 + // CHECK-NEXT: BuiltinType{{.*}} 'int' + // CHECK-NEXT: ParmVarDecl{{.*}} used t 'int' + // CHECK-NEXT: ParmVarDecl{{.*}} used u 'int *' + // CHECK-NEXT: ParmVarDecl{{.*}} used PointerParam 'int *' + // CHECK-NEXT: CompoundStmt + +// #pragma acc serial loop private(GlobalArray, PointerParam[Global]) + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'short[5]' lvalue Var{{.*}}'GlobalArray' 'short[5]' + // CHECK-NEXT: ArraySubscriptExpr{{.*}}'int' lvalue + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int *' + // CHECK-NEXT: DeclRefExpr{{.*}}'int *' lvalue ParmVar{{.*}}'PointerParam' 'int *' + // CHECK-NEXT: ImplicitCastExpr{{.*}} 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue Var{{.*}}'Global' 'int' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +// #pragma acc kernels loop private(t, u) + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue ParmVar{{.*}} 't' 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int *' lvalue ParmVar{{.*}} 'u' 'int *' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +// #pragma acc parallel loop firstprivate(t, u) + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: firstprivate clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue ParmVar{{.*}} 't' 'int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int *' lvalue ParmVar{{.*}} 'u' 'int *' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +// #pragma acc kernels loop private(t) private(u) + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue ParmVar{{.*}} 't' 'int' + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int *' lvalue ParmVar{{.*}} 'u' 'int *' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +// #pragma acc kernels loop private(t) private(NTTP, u) + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue ParmVar{{.*}} 't' 'int' + // CHECK-NEXT: private clause + // CHECK-NEXT: SubstNonTypeTemplateParmExpr{{.*}}'const unsigned int' lvalue + // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} referenced 'auto &' depth 0 index 0 NTTP + // CHECK-NEXT: DeclRefExpr{{.*}}'const unsigned int' lvalue Var{{.*}} 'CEVar' 'const unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int *' lvalue ParmVar{{.*}} 'u' 'int *' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +// #pragma acc parallel loop private(t) firstprivate(NTTP, u) + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop + // CHECK-NEXT: private clause + // CHECK-NEXT: DeclRefExpr{{.*}}'int' lvalue ParmVar{{.*}} 't' 'int' + // CHECK-NEXT: firstprivate clause + // CHECK-NEXT: SubstNonTypeTemplateParmExpr{{.*}}'const unsigned int' lvalue + // CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} referenced 'auto &' depth 0 index 0 NTTP + // CHECK-NEXT: DeclRefExpr{{.*}}'const unsigned int' lvalue Var{{.*}} 'CEVar' 'const unsigned int' + // CHECK-NEXT: DeclRefExpr{{.*}}'int *' lvalue ParmVar{{.*}} 'u' 'int *' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt +} + +void Inst() { + static constexpr unsigned CEVar = 1; + int i; + int Arr[5]; + TemplUses({}, {}, &i); +} +#endif // PCH_HELPER diff --git a/clang/test/SemaOpenACC/combined-construct-self-ast.cpp b/clang/test/SemaOpenACC/combined-construct-self-ast.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a6ba3ca6aea23a9c8aa1f57186eb35305c2f616 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-self-ast.cpp @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s + +// Test this with PCH. +// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s +// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s + +#ifndef PCH_HELPER +#define PCH_HELPER + +template +void TemplFunc() { + // CHECK: FunctionTemplateDecl{{.*}}TemplFunc + // CHECK-NEXT: TemplateTypeParmDecl + + // Match the prototype: + // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc + // CHECK-NEXT: CompoundStmt + +#pragma acc serial loop self + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc kernels loop self(T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: self clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc parallel loop self(T::SomeFloat) if (T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: self clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +#pragma acc serial loop if(T::SomeFloat) self(T::SomeFloat) + for (unsigned i = 0; i < 5; ++i); + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: self clause + // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '' lvalue + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + // + // Match the instantiation: + // CHECK: FunctionDecl{{.*}}TemplFunc{{.*}}implicit_instantiation + // CHECK-NEXT: TemplateArgument type 'InstTy' + // CHECK-NEXT: RecordType{{.*}} 'InstTy' + // CHECK-NEXT: CXXRecord{{.*}} 'InstTy' + // CHECK-NEXT: CompoundStmt + // + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}kernels loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}parallel loop + // CHECK-NEXT: self clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + + // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop + // CHECK-NEXT: if clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: self clause + // CHECK-NEXT: ImplicitCastExpr{{.*}}'bool' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'float' + // CHECK-NEXT: DeclRefExpr{{.*}} 'const float' lvalue Var{{.*}} 'SomeFloat' 'const float' + // CHECK-NEXT: NestedNameSpecifier TypeSpec 'InstTy' + // CHECK-NEXT: ForStmt + // CHECK: NullStmt + +} + +struct BoolConversion{ operator bool() const;}; +struct InstTy { + using IntTy = int; + static constexpr float SomeFloat = 5.0; + static constexpr BoolConversion BC; +}; + +void Instantiate() { + TemplFunc(); +} +#endif diff --git a/clang/test/SemaOpenACC/combined-construct-self-clause.c b/clang/test/SemaOpenACC/combined-construct-self-clause.c new file mode 100644 index 0000000000000000000000000000000000000000..39ad85eaf2e99c3bfe6fd59a7d46102c4e376c41 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-self-clause.c @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +void BoolExpr(int *I, float *F) { + typedef struct {} SomeStruct; + struct C{}; + // expected-error@+1{{expected expression}} +#pragma acc parallel loop self (struct C f()) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc serial loop self (SomeStruct) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{unexpected type name 'SomeStruct': expected expression}} +#pragma acc kernels loop self (SomeStruct()) + for (unsigned i = 0; i < 5; ++i); + + SomeStruct S; + // expected-error@+1{{statement requires expression of scalar type ('SomeStruct' invalid)}} +#pragma acc parallel loop self (S) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop self (I) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc serial loop self (F) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop self (*I < *F) + for (unsigned i = 0; i < 5; ++i); +} + +void WarnMaybeNotUsed(int val1, int val2) { + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop self if(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop self(val1) if(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop if(val1) self + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(val1) self(val2) + for (unsigned i = 0; i < 5; ++i); + + // The below don't warn because one side or the other has an error, thus is + // not added to the AST. + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc serial loop self if(invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc kernels loop self(invalid) if(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+2{{expected expression}} + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc parallel loop self() if(invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc serial loop if(invalid) self + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc kernels loop if(val2) self(invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{use of undeclared identifier 'invalid'}} +#pragma acc parallel loop if(invalid) self(val1) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{OpenACC 'self' clause is not valid on 'loop' directive}} +#pragma acc loop self + for(int i = 5; i < 10;++i); +} diff --git a/clang/test/SemaOpenACC/combined-construct-self-clause.cpp b/clang/test/SemaOpenACC/combined-construct-self-clause.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73f5a55d77c31b238075f1dafe69fd09030fc0bd --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct-self-clause.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 %s -fopenacc -verify + +struct NoBoolConversion{}; +struct BoolConversion{ + operator bool(); +}; + +template +void BoolExpr() { + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel loop self (NoBoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + // expected-error@+2{{no member named 'NotValid' in 'NoBoolConversion'}} + // expected-note@#INST{{in instantiation of function template specialization}} +#pragma acc serial loop self (T::NotValid) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc kernels loop self (BoolConversion{}) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+1{{value of type 'NoBoolConversion' is not contextually convertible to 'bool'}} +#pragma acc parallel loop self (T{}) + for (unsigned i = 0; i < 5; ++i); + +#pragma acc parallel loop self (U{}) + for (unsigned i = 0; i < 5; ++i); +} + +struct HasBool { + static constexpr bool B = true; +}; + +template +void WarnMaybeNotUsed() { + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop self if(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop self(T::B) if(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop if(T::B) self + for (unsigned i = 0; i < 5; ++i); + + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::B) self(T::B) + for (unsigned i = 0; i < 5; ++i); + + // We still warn in the cases of dependent failures, since the diagnostic + // happens immediately rather than during instantiation. + + // expected-error@+4{{no member named 'Invalid' in 'HasBool'}} + // expected-note@#NOT_USED_INST{{in instantiation of function template specialization 'WarnMaybeNotUsed' requested here}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop self if(T::Invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc serial loop self(T::Invalid) if(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc kernels loop self(T::B) if(T::Invalid) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::Invalid) self + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::Invalid) self(T::B) + for (unsigned i = 0; i < 5; ++i); + + // expected-error@+3{{no member named 'Invalid' in 'HasBool'}} + // expected-warning@+2{{OpenACC construct 'self' has no effect when an 'if' clause evaluates to true}} + // expected-note@+1{{previous clause is here}} +#pragma acc parallel loop if(T::B) self(T::Invalid) + for (unsigned i = 0; i < 5; ++i); +} + +void Instantiate() { + BoolExpr(); // #INST + WarnMaybeNotUsed(); // #NOT_USED_INST +} diff --git a/clang/test/SemaOpenACC/combined-construct.cpp b/clang/test/SemaOpenACC/combined-construct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0fd05e5a9a183b3ffd535d8ffbac9a3a4578a21 --- /dev/null +++ b/clang/test/SemaOpenACC/combined-construct.cpp @@ -0,0 +1,392 @@ +// RUN: %clang_cc1 %s -fopenacc -verify -Wno-empty-body -Wno-unused-value +namespace std { + struct random_access_iterator_tag{}; +} + +struct SomeStruct{ + void operator++(); + void operator++(int); +}; + +struct SomeIterator { + bool operator!=(SomeIterator&); + void operator++(); + void operator++(int); + int operator*(); +}; + +struct SomeRAIterator { + using iterator_category = std::random_access_iterator_tag; + SomeRAIterator(); + SomeRAIterator(int i); + + void operator=(int i); + SomeRAIterator &operator=(SomeRAIterator&); + + void operator++(int); + void operator++(); + int operator*(); + void operator+=(int); + bool operator!=(SomeRAIterator&); +}; + +struct HasIteratorCollection { + SomeIterator &begin(); + SomeIterator &end(); +}; + +struct HasRAIteratorCollection { + SomeRAIterator &begin(); + SomeRAIterator &end(); +}; + +void func_call(); + +template +void SeqLoopRules() { + + // expected-error@+3{{OpenACC 'parallel loop' construct can only be applied to a 'for' loop}} + // expected-note@+1{{'parallel loop' construct is here}} +#pragma acc parallel loop seq + while(true); + + // No rules in this section! +#pragma acc kernels loop seq + for(;;); + +#pragma acc parallel loop seq + for(float f = 0;;); + +#pragma acc serial loop seq + for(int f;;); + +#pragma acc kernels loop seq + for(int f,g;;); + +#pragma acc parallel loop seq + for(Int f;;++f); + +#pragma acc serial loop seq + for(Int *f = nullptr;;++f); + +#pragma acc kernels loop seq + for(IntPtr f = nullptr;;++f); + +#pragma acc parallel loop seq + for(Float *f = nullptr;;++f); + +#pragma acc serial loop seq + for(SomeStruct f;;); + +#pragma acc kernels loop seq + for(Struct f;;++f); + +#pragma acc parallel loop seq + for(SomeIterator f;;++f); + +#pragma acc serial loop seq + for(Iterator f;;++f); + +#pragma acc kernels loop seq + for(SomeRAIterator f;;++f); + +#pragma acc parallel loop seq + for(RandAccessIterator f;;++f); + +#pragma acc kernels loop seq + for(Int f;;); + +#pragma acc parallel loop seq + for(Int f;;++f); + +#pragma acc serial loop seq + for(Int f;;f+=1); + + int i; +#pragma acc kernels loop seq + for(Int f;;i+=1); + +#pragma acc parallel loop seq + for(Int f;;i++); + +#pragma acc serial loop seq + for(RandAccessIterator f;;i++); + +#pragma acc kernels loop seq + for(RandAccessIterator f;;func_call()); + + Int Array[5]; +#pragma acc parallel loop seq + for(auto X : Array); + +#pragma acc serial loop seq + for(auto X : HasIteratorCollection{}); + +#pragma acc kernels loop seq + for(auto X : HasRAIteratorCollection{}); + + RandAccessIterator f, end; +#pragma acc parallel loop seq + for(f;f != end;f++); + +#pragma acc kernels loop seq + for(f = 0;;++f); + +#pragma acc parallel loop seq + for(f = 0;;f++); + +#pragma acc serial loop seq + for(f = 0;;f+=1); +} + + +template +void LoopRules() { + // expected-error@+3{{OpenACC 'parallel loop' construct can only be applied to a 'for' loop}} + // expected-note@+1{{'parallel loop' construct is here}} +#pragma acc parallel loop + while(true); + + // Loop variable must be integer, pointer, or random_access_iterator +#pragma acc kernels loop + // expected-error@+6{{OpenACC 'kernels loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'kernels loop' construct is here}} + // expected-error@+4{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-4{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'kernels loop' construct is here}} + for(;;); + +#pragma acc parallel loop + // expected-error@+6{{loop variable of loop associated with an OpenACC 'parallel loop' construct must be of integer, pointer, or random-access-iterator type (is 'float')}} + // expected-note@-2{{'parallel loop' construct is here}} + // expected-error@+4{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-4{{'parallel loop' construct is here}} + // expected-error@+2{{OpenACC 'parallel loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'parallel loop' construct is here}} + for(float f = 0;;); + +#pragma acc serial loop + // expected-error@+6{{OpenACC 'serial loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'serial loop' construct is here}} + // expected-error@+4{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-4{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'serial loop' construct is here}} + for(int f;;); + +#pragma acc kernels loop + // expected-error@+6 2{{OpenACC 'kernels loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2 2{{'kernels loop' construct is here}} + // expected-error@+4{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-4{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'kernels loop' construct is here}} + for(int f,g;;); + +#pragma acc parallel loop + // expected-error@+4{{OpenACC 'parallel loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'parallel loop' construct is here}} + // expected-error@+2{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-4{{'parallel loop' construct is here}} + for(Int f;;++f); + +#pragma acc serial loop + // expected-error@+2{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-2{{'serial loop' construct is here}} + for(Int *f = nullptr;;++f); + +#pragma acc kernels loop + // expected-error@+2{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-2{{'kernels loop' construct is here}} + for(IntPtr f = nullptr;;++f); + +#pragma acc parallel loop + // expected-error@+2{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-2{{'parallel loop' construct is here}} + for(Float *f = nullptr;;++f); + +#pragma acc serial loop + // expected-error@+6{{loop variable of loop associated with an OpenACC 'serial loop' construct must be of integer, pointer, or random-access-iterator type (is 'SomeStruct')}} + // expected-note@-2{{'serial loop' construct is here}} + // expected-error@+4{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-4{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'serial loop' construct is here}} + for(SomeStruct f;;); + +#pragma acc kernels loop + // expected-error@+4{{loop variable of loop associated with an OpenACC 'kernels loop' construct must be of integer, pointer, or random-access-iterator type (is 'SomeStruct')}} + // expected-note@-2{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-4{{'kernels loop' construct is here}} + for(Struct f;;++f); + +#pragma acc parallel loop + // expected-error@+4{{loop variable of loop associated with an OpenACC 'parallel loop' construct must be of integer, pointer, or random-access-iterator type (is 'SomeIterator')}} + // expected-note@-2{{'parallel loop' construct is here}} + // expected-error@+2{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-4{{'parallel loop' construct is here}} + for(SomeIterator f;;++f); + +#pragma acc serial loop + // expected-error@+4{{loop variable of loop associated with an OpenACC 'serial loop' construct must be of integer, pointer, or random-access-iterator type (is 'SomeIterator')}} + // expected-note@-2{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-4{{'serial loop' construct is here}} + for(Iterator f;;++f); + +#pragma acc kernels loop + // expected-error@+2{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-2{{'kernels loop' construct is here}} + for(SomeRAIterator f;;++f); + +#pragma acc parallel loop + // expected-error@+2{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-2{{'parallel loop' construct is here}} + for(RandAccessIterator f;;++f); + + Int i; +#pragma acc serial loop + // expected-error@+4{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-2{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-4{{'serial loop' construct is here}} + for( i = 0;;); + +#pragma acc kernels loop + // expected-error@+6 2{{OpenACC 'kernels loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2 2{{'kernels loop' construct is here}} + // expected-error@+4{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-4{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'kernels loop' construct is here}} + for( i;;); + +#pragma acc parallel loop + // expected-error@+6{{OpenACC 'parallel loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'parallel loop' construct is here}} + // expected-error@+4{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-4{{'parallel loop' construct is here}} + // expected-error@+2{{OpenACC 'parallel loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'parallel loop' construct is here}} + for( int j ;;); + +#pragma acc serial loop + // expected-error@+6 2{{OpenACC 'serial loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2 2{{'serial loop' construct is here}} + // expected-error@+4{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-4{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'serial loop' construct is here}} + for( int j, k = 0;;); + +#pragma acc kernels loop + // expected-error@+6{{OpenACC 'kernels loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'kernels loop' construct is here}} + // expected-error@+4{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-4{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'kernels loop' construct is here}} + for(Int f;;); + +#pragma acc parallel loop + // expected-error@+4{{OpenACC 'parallel loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'parallel loop' construct is here}} + // expected-error@+2{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-4{{'parallel loop' construct is here}} + for(Int f;;++f); + +#pragma acc serial loop + // expected-error@+4{{OpenACC 'serial loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-4{{'serial loop' construct is here}} + for(Int f;;f+=1); + +#pragma acc kernels loop + // expected-error@+6{{OpenACC 'kernels loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'kernels loop' construct is here}} + // expected-error@+4{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-4{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'kernels loop' construct is here}} + for(Int f;;i+=1); + +#pragma acc parallel loop + // expected-error@+6{{OpenACC 'parallel loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2{{'parallel loop' construct is here}} + // expected-error@+4{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-4{{'parallel loop' construct is here}} + // expected-error@+2{{OpenACC 'parallel loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-6{{'parallel loop' construct is here}} + for(Int f;;i++); + +#pragma acc serial loop + // expected-error@+4{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-2{{'serial loop' construct is here}} + // expected-error@+2{{OpenACC 'serial loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-4{{'serial loop' construct is here}} + for(RandAccessIterator f;;i++); + +#pragma acc kernels loop + // expected-error@+4{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-2{{'kernels loop' construct is here}} + // expected-error@+2{{OpenACC 'kernels loop' variable must monotonically increase or decrease ('++', '--', or compound assignment)}} + // expected-note@-4{{'kernels loop' construct is here}} + for(RandAccessIterator f;;func_call()); + + // Not much we can do here other than check for random access iterator. + Int Array[5]; +#pragma acc parallel loop + for(auto X : Array); + +#pragma acc kernels loop + // expected-error@+2 2{{loop variable of loop associated with an OpenACC 'kernels loop' construct must be of integer, pointer, or random-access-iterator type (is 'SomeIterator')}} + // expected-note@-2 2{{'kernels loop' construct is here}} + for(auto X : HasIteratorCollection{}); + +#pragma acc serial loop + for(auto X : HasRAIteratorCollection{}); + + RandAccessIterator end; +#pragma acc parallel loop + for(RandAccessIterator f = 0; f != end; ++f); + + RandAccessIterator f; +#pragma acc serial loop + // expected-error@+2 2{{OpenACC 'serial loop' construct must have initialization clause in canonical form ('var = init' or 'T var = init'}} + // expected-note@-2 2{{'serial loop' construct is here}} + for(f;f != end;f++); + +#pragma acc kernels loop + // expected-error@+2{{OpenACC 'kernels loop' construct must have a terminating condition}} + // expected-note@-2{{'kernels loop' construct is here}} + for(f = 0;;++f); + +#pragma acc parallel loop + // expected-error@+2{{OpenACC 'parallel loop' construct must have a terminating condition}} + // expected-note@-2{{'parallel loop' construct is here}} + for(f = 0;;f++); + +#pragma acc serial loop + // expected-error@+2{{OpenACC 'serial loop' construct must have a terminating condition}} + // expected-note@-2{{'serial loop' construct is here}} + for(f = 0;;f+=1); + +#pragma acc kernels loop + for(f = 0;f != end;++f); + +#pragma acc parallel loop + for(f = 0;f != end;f++); + +#pragma acc parallel loop + for(f = 0;f != end;f+=1); +} + +void inst() { + SeqLoopRules(); + // expected-note@+1{{in instantiation of function template specialization}} + LoopRules(); +} + diff --git a/clang/test/SemaOpenACC/compute-construct-ast.cpp b/clang/test/SemaOpenACC/compute-construct-ast.cpp index 7a33aeb80570c7b7a1cd44cfaf59d94b7b512da4..b24ad910874046cfc203c246dcac40ee78362125 100644 --- a/clang/test/SemaOpenACC/compute-construct-ast.cpp +++ b/clang/test/SemaOpenACC/compute-construct-ast.cpp @@ -8,7 +8,6 @@ #define PCH_HELPER void NormalFunc() { - // FIXME: Add a test once we have clauses for this. // CHECK-LABEL: NormalFunc // CHECK-NEXT: CompoundStmt // CHECK-NEXT: OpenACCComputeConstruct {{.*}}parallel @@ -24,7 +23,6 @@ void NormalFunc() { #pragma acc parallel default(present) {} } - // FIXME: Add a test once we have clauses for this. // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial // CHECK-NEXT: CompoundStmt #pragma acc serial @@ -36,7 +34,6 @@ void NormalFunc() { #pragma acc serial {} } - // FIXME: Add a test once we have clauses for this. // CHECK-NEXT: OpenACCComputeConstruct {{.*}}kernels // CHECK-NEXT: CompoundStmt #pragma acc kernels diff --git a/clang/test/SemaOpenACC/compute-construct-default-clause.c b/clang/test/SemaOpenACC/compute-construct-default-clause.c index a8d0c2b705d22d96c5ef5426d4722e6fafbf6305..e71fee47e8a29214f0a2a89b385acad018a24b12 100644 --- a/clang/test/SemaOpenACC/compute-construct-default-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-default-clause.c @@ -16,23 +16,16 @@ void SingleOnly() { #pragma acc kernels self default(present) present(i) default(none) copy(i) while(0); - // expected-warning@+6{{OpenACC construct 'parallel loop' not yet implemented}} - // expected-warning@+5{{OpenACC clause 'self' not yet implemented}} - // expected-warning@+4{{OpenACC clause 'default' not yet implemented}} - // expected-warning@+3{{OpenACC clause 'private' not yet implemented}} - // expected-warning@+2{{OpenACC clause 'default' not yet implemented}} - // expected-warning@+1{{OpenACC clause 'copy' not yet implemented}} + // expected-warning@+3{{OpenACC clause 'copy' not yet implemented}} + // expected-error@+2{{OpenACC 'default' clause cannot appear more than once on a 'parallel loop' directive}} + // expected-note@+1{{previous clause is here}} #pragma acc parallel loop self default(present) private(i) default(none) copy(i) for(int i = 0; i < 5; ++i); - // expected-warning@+3{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented}} // expected-error@+1{{expected '('}} #pragma acc serial loop self default private(i) default(none) if(i) for(int i = 0; i < 5; ++i); - // expected-warning@+2{{OpenACC construct 'kernels loop' not yet implemented}} - // expected-warning@+1{{OpenACC clause 'default' not yet implemented}} #pragma acc kernels loop default(none) for(int i = 0; i < 5; ++i); diff --git a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c index aaf8b76e1f3dfbee22c4aac252d801cd41a6f505..0ae972d2a99ff4beeb7a01996b8b02090aa687df 100644 --- a/clang/test/SemaOpenACC/compute-construct-device_type-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-device_type-clause.c @@ -44,11 +44,11 @@ void uses() { // Only 'async', 'wait', num_gangs', 'num_workers', 'vector_length' allowed after 'device_type'. - // expected-error@+2{{OpenACC clause 'finalize' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'finalize' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) finalize while(1); - // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) if_present while(1); @@ -64,133 +64,133 @@ void uses() { // expected-error@+1{{OpenACC 'worker' clause is not valid on 'kernels' directive}} #pragma acc kernels device_type(*) worker while(1); - // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'nohost' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) nohost while(1); - // expected-error@+2{{OpenACC clause 'default' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'default' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) default(none) while(1); - // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) if(1) while(1); - // expected-error@+2{{OpenACC clause 'self' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'self' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) self while(1); int Var; int *VarPtr; - // expected-error@+2{{OpenACC clause 'copy' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'copy' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) copy(Var) while(1); - // expected-error@+2{{OpenACC clause 'pcopy' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'pcopy' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) pcopy(Var) while(1); - // expected-error@+2{{OpenACC clause 'present_or_copy' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'present_or_copy' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) present_or_copy(Var) while(1); - // expected-error@+2{{OpenACC clause 'use_device' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'use_device' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) use_device(Var) while(1); - // expected-error@+2{{OpenACC clause 'attach' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'attach' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) attach(Var) while(1); - // expected-error@+2{{OpenACC clause 'delete' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'delete' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) delete(Var) while(1); - // expected-error@+2{{OpenACC clause 'detach' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'detach' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) detach(Var) while(1); - // expected-error@+2{{OpenACC clause 'device' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'device' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) device(VarPtr) while(1); - // expected-error@+2{{OpenACC clause 'deviceptr' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'deviceptr' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) deviceptr(VarPtr) while(1); - // expected-error@+2{{OpenACC clause 'device_resident' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'device_resident' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) device_resident(VarPtr) while(1); - // expected-error@+2{{OpenACC clause 'firstprivate' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'firstprivate' may not follow a 'device_type' clause in a 'parallel' construct}} // expected-note@+1{{previous clause is here}} #pragma acc parallel device_type(*) firstprivate(Var) while(1); - // expected-error@+2{{OpenACC clause 'host' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'host' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) host(Var) while(1); - // expected-error@+2{{OpenACC clause 'link' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'link' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) link(Var) while(1); - // expected-error@+2{{OpenACC clause 'no_create' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'no_create' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) no_create(Var) while(1); - // expected-error@+2{{OpenACC clause 'present' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'present' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) present(Var) while(1); - // expected-error@+2{{OpenACC clause 'private' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'private' may not follow a 'device_type' clause in a 'parallel' construct}} // expected-note@+1{{previous clause is here}} #pragma acc parallel device_type(*) private(Var) while(1); - // expected-error@+2{{OpenACC clause 'copyout' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'copyout' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) copyout(Var) while(1); - // expected-error@+2{{OpenACC clause 'pcopyout' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'pcopyout' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) pcopyout(Var) while(1); - // expected-error@+2{{OpenACC clause 'present_or_copyout' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'present_or_copyout' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) present_or_copyout(Var) while(1); - // expected-error@+2{{OpenACC clause 'copyin' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'copyin' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) copyin(Var) while(1); - // expected-error@+2{{OpenACC clause 'pcopyin' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'pcopyin' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) pcopyin(Var) while(1); - // expected-error@+2{{OpenACC clause 'present_or_copyin' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'present_or_copyin' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) present_or_copyin(Var) while(1); - // expected-error@+2{{OpenACC clause 'create' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'create' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) create(Var) while(1); - // expected-error@+2{{OpenACC clause 'pcreate' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'pcreate' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) pcreate(Var) while(1); - // expected-error@+2{{OpenACC clause 'present_or_create' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'present_or_create' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) present_or_create(Var) while(1); - // expected-error@+2{{OpenACC clause 'reduction' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'reduction' may not follow a 'device_type' clause in a 'serial' construct}} // expected-note@+1{{previous clause is here}} #pragma acc serial device_type(*) reduction(+:Var) while(1); // expected-error@+1{{OpenACC 'collapse' clause is not valid on 'kernels' directive}} #pragma acc kernels device_type(*) collapse(1) while(1); - // expected-error@+2{{OpenACC clause 'bind' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'bind' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) bind(Var) while(1); @@ -200,11 +200,11 @@ void uses() { while(1); #pragma acc kernels device_type(*) num_workers(1) while(1); - // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'device_num' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) device_num(1) while(1); - // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a compute construct}} + // expected-error@+2{{OpenACC clause 'default_async' may not follow a 'device_type' clause in a 'kernels' construct}} // expected-note@+1{{previous clause is here}} #pragma acc kernels device_type(*) default_async(1) while(1); diff --git a/clang/test/SemaOpenACC/compute-construct-firstprivate-clause.cpp b/clang/test/SemaOpenACC/compute-construct-firstprivate-clause.cpp index 161e4012c08d56fb05b98d782275e10352ee2c41..4bee51530f44a3f586a8ca270b47e51cc1adc513 100644 --- a/clang/test/SemaOpenACC/compute-construct-firstprivate-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-firstprivate-clause.cpp @@ -60,34 +60,34 @@ void uses(int IntParam, char *PointerParam, float ArrayParam[5], Complete Compos template void TemplUses(T t, T (&arrayT)[I], V TemplComp) { // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} -#pragma acc parallel private(+t) +#pragma acc parallel firstprivate(+t) while(true); // NTTP's are only valid if it is a reference to something. // expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} // expected-note@#TEMPL_USES_INST{{in instantiation of}} -#pragma acc parallel private(I) +#pragma acc parallel firstprivate(I) while(true); // expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} -#pragma acc parallel private(t, I) +#pragma acc parallel firstprivate(t, I) while(true); -#pragma acc parallel private(arrayT) +#pragma acc parallel firstprivate(arrayT) while(true); -#pragma acc parallel private(TemplComp) +#pragma acc parallel firstprivate(TemplComp) while(true); -#pragma acc parallel private(TemplComp.PointerMember[5]) +#pragma acc parallel firstprivate(TemplComp.PointerMember[5]) while(true); int *Pointer; -#pragma acc parallel private(Pointer[:I]) +#pragma acc parallel firstprivate(Pointer[:I]) while(true); -#pragma acc parallel private(Pointer[:t]) +#pragma acc parallel firstprivate(Pointer[:t]) while(true); // expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} -#pragma acc parallel private(Pointer[1:]) +#pragma acc parallel firstprivate(Pointer[1:]) while(true); } @@ -96,10 +96,10 @@ void NTTP() { // NTTP's are only valid if it is a reference to something. // expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}} // expected-note@#NTTP_INST{{in instantiation of}} -#pragma acc parallel private(I) +#pragma acc parallel firstprivate(I) while(true); -#pragma acc parallel private(NTTP_REF) +#pragma acc parallel firstprivate(NTTP_REF) while(true); } diff --git a/clang/test/SemaOpenACC/compute-construct-if-clause.c b/clang/test/SemaOpenACC/compute-construct-if-clause.c index 2fbf49f207a74e6df3549985a86a065c79242587..7cdc35275acce0ed6cd9bfd411212cb420bd695f 100644 --- a/clang/test/SemaOpenACC/compute-construct-if-clause.c +++ b/clang/test/SemaOpenACC/compute-construct-if-clause.c @@ -47,16 +47,10 @@ void BoolExpr(int *I, float *F) { // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc data if (*I < *F) while(0); - // expected-warning@+2{{OpenACC construct 'parallel loop' not yet implemented}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc parallel loop if (*I < *F) for(int i = 0; i < 5; ++i); - // expected-warning@+2{{OpenACC construct 'serial loop' not yet implemented}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc serial loop if (*I < *F) for(int i = 0; i < 5; ++i); - // expected-warning@+2{{OpenACC construct 'kernels loop' not yet implemented}} - // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} #pragma acc kernels loop if (*I < *F) for(int i = 0; i < 5; ++i); diff --git a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp index ec3df87a065572f71518fccb8384eb3e36043240..c50f52afda7c1c8939707403b5df1ccc57a98978 100644 --- a/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp +++ b/clang/test/SemaOpenACC/compute-construct-num_gangs-clause.cpp @@ -105,7 +105,6 @@ void Test() { // expected-error@+1{{OpenACC 'num_gangs' clause is not valid on 'serial' directive}} #pragma acc serial num_gangs(Explicit, NC, Ambiguous) while(1); - // TODO } struct HasInt { diff --git a/clang/test/SemaOpenACC/loop-construct.cpp b/clang/test/SemaOpenACC/loop-construct.cpp index 68dca49622b3d8fb291650d15b74ce7bed537c7f..5616cac6de37b41f2af3164f1365e2ec2c349c4d 100644 --- a/clang/test/SemaOpenACC/loop-construct.cpp +++ b/clang/test/SemaOpenACC/loop-construct.cpp @@ -28,7 +28,6 @@ struct SomeRAIterator { int operator*(); void operator+=(int); bool operator!=(SomeRAIterator&); - // TODO }; struct HasIteratorCollection { diff --git a/clang/test/SemaOpenACC/no-branch-in-out.c b/clang/test/SemaOpenACC/no-branch-in-out.c index 5fff18eb7cdd7b08c2d675cbdbc532eab935d223..37126d8f2200e7050fc37c935c7a3dbba3349157 100644 --- a/clang/test/SemaOpenACC/no-branch-in-out.c +++ b/clang/test/SemaOpenACC/no-branch-in-out.c @@ -14,7 +14,22 @@ void BreakContinue() { if (i == 2) continue; - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } + +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + switch(i) { + case 0: + break; // leaves switch, not 'for'. + default: + i +=2; + break; + } + if (i == 2) + continue; + + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } int j; @@ -22,7 +37,7 @@ void BreakContinue() { case 0: #pragma acc parallel { - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } case 1: #pragma acc parallel @@ -34,19 +49,37 @@ void BreakContinue() { #pragma acc parallel for(int i = 0; i < 5; ++i) { if (i > 1) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } + +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + if (i > 1) + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } #pragma acc serial for(int i = 0; i < 5; ++i) { if (i > 1) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } + +#pragma acc serial loop + for(int i = 0; i < 5; ++i) { + if (i > 1) + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } #pragma acc kernels for(int i = 0; i < 5; ++i) { if (i > 1) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } + +#pragma acc kernels loop + for(int i = 0; i < 5; ++i) { + if (i > 1) + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } #pragma acc parallel @@ -66,7 +99,7 @@ void BreakContinue() { for (int i =0; i < 5; ++i) { #pragma acc parallel { - continue; // expected-error{{invalid branch out of OpenACC Compute Construct}} + continue; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } } @@ -75,6 +108,11 @@ void BreakContinue() { continue; } +#pragma acc parallel loop + for (int i =0; i < 5; ++i) { + continue; + } + #pragma acc parallel for (int i =0; i < 5; ++i) { { @@ -82,10 +120,17 @@ void BreakContinue() { } } +#pragma acc parallel loop + for (int i =0; i < 5; ++i) { + { + continue; + } + } + for (int i =0; i < 5; ++i) { #pragma acc parallel { - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } } @@ -93,52 +138,79 @@ void BreakContinue() { while (j) { --j; if (j > 4) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } - #pragma acc parallel do { --j; if (j > 4) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } while (j ); - } void Return() { #pragma acc parallel { - return;// expected-error{{invalid return out of OpenACC Compute Construct}} + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} + } + +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} } #pragma acc serial { - return;// expected-error{{invalid return out of OpenACC Compute Construct}} + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} + } + +#pragma acc serial loop + for (unsigned i = 0; i < 5; ++i) { + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} } #pragma acc kernels { - return;// expected-error{{invalid return out of OpenACC Compute Construct}} + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} + } + +#pragma acc kernels loop + for (unsigned i = 0; i < 5; ++i) { + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} } #pragma acc parallel { { - return;// expected-error{{invalid return out of OpenACC Compute Construct}} + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} + } + } + +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + { + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} } } #pragma acc parallel { for (int i = 0; i < 5; ++i) { - return;// expected-error{{invalid return out of OpenACC Compute Construct}} + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} + } + } + +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + for (int i = 0; i < 5; ++i) { + return;// expected-error{{invalid return out of OpenACC Compute/Combined Construct}} } } } void Goto() { int j; -#pragma acc parallel // expected-note{{invalid branch out of OpenACC Compute Construct}} +#pragma acc parallel // expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} while(j) { if (j <3) goto LABEL; // expected-error{{cannot jump from this goto statement to its label}} @@ -148,31 +220,56 @@ LABEL: {} goto LABEL_IN; // expected-error{{cannot jump from this goto statement to its label}} - -#pragma acc parallel // expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc parallel // expected-note{{invalid branch into OpenACC Compute/Combined Construct}} for(int i = 0; i < 5; ++i) { LABEL_IN: {} } + int i; + goto LABEL_IN2; // expected-error{{cannot jump from this goto statement to its label}} +#pragma acc parallel loop // expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for(i = 0; i < 5; ++i) { +LABEL_IN2: + {} + } + #pragma acc parallel for(int i = 0; i < 5; ++i) { LABEL_NOT_CALLED: {} } +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { +LABEL_NOT_CALLED2: + {} + } + #pragma acc parallel { goto ANOTHER_LOOP; // expected-error{{cannot jump from this goto statement to its label}} } -#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + goto ANOTHER_LOOP2; // expected-error{{cannot jump from this goto statement to its label}} + + } + +#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { ANOTHER_LOOP: {} } +#pragma acc parallel loop// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { +ANOTHER_LOOP2: + {} + } + #pragma acc parallel { while (j) { @@ -187,34 +284,63 @@ LABEL2: {} } +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + while (j) { + --j; + if (j < 3) + goto LABEL2_2; + + if (j > 4) + break; + } +LABEL2_2: + {} + } + + #pragma acc parallel do { if (j < 3) goto LABEL3; if (j > 4) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} LABEL3: {} } while (j); + LABEL4: {} -#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}} + +#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} { goto LABEL4;// expected-error{{cannot jump from this goto statement to its label}} } -#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc parallel loop// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { + goto LABEL4;// expected-error{{cannot jump from this goto statement to its label}} + } + +#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { LABEL5: {} } +#pragma acc parallel loop// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { +LABEL5_2: + {} + } + { goto LABEL5;// expected-error{{cannot jump from this goto statement to its label}} + goto LABEL5_2;// expected-error{{cannot jump from this goto statement to its label}} } #pragma acc parallel @@ -225,86 +351,153 @@ LABEL6: } +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { +LABEL6_2: + {} + goto LABEL6_2; + + } + #pragma acc parallel goto LABEL7; // expected-error{{cannot jump from this goto statement to its label}} -#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { LABEL7:{} } #pragma acc parallel LABEL8:{} -#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}} +#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} { goto LABEL8;// expected-error{{cannot jump from this goto statement to its label}} } - -#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { LABEL9:{} } ({goto LABEL9;});// expected-error{{cannot jump from this goto statement to its label}} -#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}} - { +#pragma acc parallel loop// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { +LABEL9_2:{} + } + + ({goto LABEL9_2;});// expected-error{{cannot jump from this goto statement to its label}} + + +#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { ({goto LABEL10;});// expected-error{{cannot jump from this goto statement to its label}} } LABEL10:{} +#pragma acc parallel loop// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { + ({goto LABEL10_2;});// expected-error{{cannot jump from this goto statement to its label}} + } + +LABEL10_2:{} + ({goto LABEL11;});// expected-error{{cannot jump from this goto statement to its label}} -#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { LABEL11:{} } + ({goto LABEL11_2;});// expected-error{{cannot jump from this goto statement to its label}} +#pragma acc parallel loop// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { +LABEL11_2:{} + } + LABEL12:{} -#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}} +#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} { ({goto LABEL12;});// expected-error{{cannot jump from this goto statement to its label}} } +LABEL12_2:{} +#pragma acc parallel loop// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { + ({goto LABEL12_2;});// expected-error{{cannot jump from this goto statement to its label}} + } + #pragma acc parallel { ({goto LABEL13;}); LABEL13:{} } +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + ({goto LABEL13_2;}); +LABEL13_2:{} + } + #pragma acc parallel { LABEL14:{} ({goto LABEL14;}); } +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { + LABEL14_2:{} + ({goto LABEL14_2;}); + } + ({goto LABEL15;});// expected-error{{cannot jump from this goto statement to its label}} -#pragma acc serial// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc serial// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { LABEL15:{} } + ({goto LABEL15_2;});// expected-error{{cannot jump from this goto statement to its label}} +#pragma acc serial loop// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { +LABEL15_2:{} + } LABEL16:{} -#pragma acc serial// expected-note{{invalid branch out of OpenACC Compute Construct}} +#pragma acc serial// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} { ({goto LABEL16;});// expected-error{{cannot jump from this goto statement to its label}} } +LABEL16_2:{} +#pragma acc serial loop// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { + ({goto LABEL16_2;});// expected-error{{cannot jump from this goto statement to its label}} + } ({goto LABEL17;});// expected-error{{cannot jump from this goto statement to its label}} -#pragma acc kernels// expected-note{{invalid branch into OpenACC Compute Construct}} +#pragma acc kernels// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} { LABEL17:{} } + ({goto LABEL17_2;});// expected-error{{cannot jump from this goto statement to its label}} +#pragma acc kernels loop// expected-note{{invalid branch into OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { +LABEL17_2:{} + } + LABEL18:{} -#pragma acc kernels// expected-note{{invalid branch out of OpenACC Compute Construct}} +#pragma acc kernels// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} { ({goto LABEL18;});// expected-error{{cannot jump from this goto statement to its label}} } +LABEL18_2:{} +#pragma acc kernels loop// expected-note{{invalid branch out of OpenACC Compute/Combined Construct}} + for (unsigned i = 0; i < 5; ++i) { + ({goto LABEL18_2;});// expected-error{{cannot jump from this goto statement to its label}} + } } void IndirectGoto1() { @@ -313,6 +506,17 @@ void IndirectGoto1() { { LABEL1:{} ptr = &&LABEL1; + goto *ptr; + + } +} + +void IndirectGoto1_Loop() { + void *ptr; +#pragma acc parallel loop + for (unsigned i = 0; i < 5; ++i) { +LABEL1:{} + ptr = &&LABEL1; goto *ptr; @@ -327,7 +531,15 @@ LABEL2:{} // #GOTOLBL2 { // expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}} // expected-note@#GOTOLBL2{{possible target of indirect goto statement}} -// expected-note@#GOTOPAR2{{invalid branch out of OpenACC Compute Construct}} +// expected-note@#GOTOPAR2{{invalid branch out of OpenACC Compute/Combined Construct}} + goto *ptr; + } + +#pragma acc parallel loop // #GOTOPAR_LOOP2 + for (unsigned i = 0; i < 5; ++i) { +// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}} +// expected-note@#GOTOLBL2{{possible target of indirect goto statement}} +// expected-note@#GOTOPAR_LOOP2{{invalid branch out of OpenACC Compute/Combined Construct}} goto *ptr; } } @@ -341,7 +553,20 @@ LABEL3:{} // #GOTOLBL3 } // expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}} // expected-note@#GOTOLBL3{{possible target of indirect goto statement}} -// expected-note@#GOTOPAR3{{invalid branch into OpenACC Compute Construct}} +// expected-note@#GOTOPAR3{{invalid branch into OpenACC Compute/Combined Construct}} + goto *ptr; +} + +void IndirectGoto3_Loop() { + void* ptr; +#pragma acc parallel loop// #GOTOPAR_LOOP3 + for (unsigned i = 0; i < 5; ++i) { +LABEL3:{} // #GOTOLBL3_2 + ptr = &&LABEL3; + } +// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}} +// expected-note@#GOTOLBL3_2{{possible target of indirect goto statement}} +// expected-note@#GOTOPAR_LOOP3{{invalid branch into OpenACC Compute/Combined Construct}} goto *ptr; } @@ -353,7 +578,7 @@ LABEL4:{} ptr = &&LABEL4; // expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}} // expected-note@#GOTOLBL5{{possible target of indirect goto statement}} -// expected-note@#GOTOPAR4{{invalid branch out of OpenACC Compute Construct}} +// expected-note@#GOTOPAR4{{invalid branch out of OpenACC Compute/Combined Construct}} goto *ptr; } LABEL5:// #GOTOLBL5 @@ -361,12 +586,28 @@ LABEL5:// #GOTOLBL5 ptr=&&LABEL5; } +void IndirectGoto4_2() { + void* ptr; +#pragma acc parallel loop // #GOTOPAR_LOOP4 + for (unsigned i = 0; i < 5; ++i) { +LABEL4:{} + ptr = &&LABEL4; +// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}} +// expected-note@#GOTOLBL_LOOP5{{possible target of indirect goto statement}} +// expected-note@#GOTOPAR_LOOP4{{invalid branch out of OpenACC Compute/Combined Construct}} + goto *ptr; + } +LABEL5:// #GOTOLBL_LOOP5 + + ptr=&&LABEL5; +} + void DuffsDevice() { int j; switch (j) { #pragma acc parallel for(int i =0; i < 5; ++i) { - case 0: // expected-error{{invalid branch into OpenACC Compute Construct}} + case 0: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -374,7 +615,7 @@ void DuffsDevice() { switch (j) { #pragma acc parallel for(int i =0; i < 5; ++i) { - default: // expected-error{{invalid branch into OpenACC Compute Construct}} + default: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -382,7 +623,7 @@ void DuffsDevice() { switch (j) { #pragma acc kernels for(int i =0; i < 5; ++i) { - default: // expected-error{{invalid branch into OpenACC Compute Construct}} + default: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -390,7 +631,7 @@ void DuffsDevice() { switch (j) { #pragma acc parallel for(int i =0; i < 5; ++i) { - case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}} + case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -398,7 +639,50 @@ void DuffsDevice() { switch (j) { #pragma acc serial for(int i =0; i < 5; ++i) { - case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}} + case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } +} + +void DuffsDeviceLoop() { + int j; + switch (j) { +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + case 0: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + default: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc kernels loop + for(int i =0; i < 5; ++i) { + default: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc serial loop + for(int i =0; i < 5; ++i) { + case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } diff --git a/clang/test/SemaOpenACC/no-branch-in-out.cpp b/clang/test/SemaOpenACC/no-branch-in-out.cpp index bc559f1898f1bc2e1d7ac4a4b31f978c47b38546..7ddc48cfb1791ea4aaa4cb4abfff50d8630594da 100644 --- a/clang/test/SemaOpenACC/no-branch-in-out.cpp +++ b/clang/test/SemaOpenACC/no-branch-in-out.cpp @@ -7,11 +7,24 @@ void ReturnTest() { (void)[]() { return; }; } +#pragma acc parallel loop + for (int i = 0; i < 5; ++i) { + (void)[]() { return; }; + } + + #pragma acc parallel { try {} catch(...){ - return; // expected-error{{invalid return out of OpenACC Compute Construct}} + return; // expected-error{{invalid return out of OpenACC Compute/Combined Construct}} + } + } +#pragma acc parallel loop + for (int i = 0; i < 5; ++i) { + try {} + catch(...){ + return; // expected-error{{invalid return out of OpenACC Compute/Combined Construct}} } } } @@ -30,7 +43,21 @@ void BreakContinue() { if (i == 2) continue; - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + switch(i) { + case 0: + break; // leaves switch, not 'for'. + default: + i +=2; + break; + } + if (i == 2) + continue; + + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } int j; @@ -38,7 +65,7 @@ void BreakContinue() { case 0: #pragma acc parallel { - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } case 1: #pragma acc parallel @@ -46,11 +73,29 @@ void BreakContinue() { } break; } + switch(j) { + case 0: +#pragma acc parallel loop + for (int i = 0; i < 5; ++i) { + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } + case 1: +#pragma acc parallel loop + for (int i = 0; i < 5; ++i) { + } + break; + } #pragma acc parallel for(int i = 0; i < 5; ++i) { if (i > 1) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} + } + +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + if (i > 1) + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } #pragma acc parallel @@ -59,6 +104,13 @@ void BreakContinue() { break; } +#pragma acc parallel loop + for (int i = 0; i < 5; ++i) + switch(j) { + case 1: + break; + } + #pragma acc parallel { for(int i = 1; i < 100; i++) { @@ -70,7 +122,7 @@ void BreakContinue() { for (int i =0; i < 5; ++i) { #pragma acc parallel { - continue; // expected-error{{invalid branch out of OpenACC Compute Construct}} + continue; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } } @@ -79,6 +131,11 @@ void BreakContinue() { continue; } +#pragma acc parallel loop + for (int i =0; i < 5; ++i) { + continue; + } + #pragma acc parallel for (int i =0; i < 5; ++i) { { @@ -86,10 +143,17 @@ void BreakContinue() { } } +#pragma acc parallel loop + for (int i =0; i < 5; ++i) { + { + continue; + } + } + for (int i =0; i < 5; ++i) { #pragma acc parallel { - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } } @@ -97,14 +161,14 @@ void BreakContinue() { while (j) { --j; if (j > 4) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } #pragma acc parallel do { --j; if (j > 4) - break; // expected-error{{invalid branch out of OpenACC Compute Construct}} + break; // expected-error{{invalid branch out of OpenACC Compute/Combined Construct}} } while (j ); } @@ -114,7 +178,15 @@ void DuffsDevice() { switch (j) { #pragma acc parallel for(int i =0; i < 5; ++i) { - case 0: // expected-error{{invalid branch into OpenACC Compute Construct}} + case 0: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + case 0: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -122,7 +194,15 @@ void DuffsDevice() { switch (j) { #pragma acc parallel for(int i =0; i < 5; ++i) { - default: // expected-error{{invalid branch into OpenACC Compute Construct}} + default: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + default: // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -130,7 +210,15 @@ void DuffsDevice() { switch (j) { #pragma acc parallel for(int i =0; i < 5; ++i) { - case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}} + case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} + {} + } + } + + switch (j) { +#pragma acc parallel loop + for(int i =0; i < 5; ++i) { + case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute/Combined Construct}} {} } } @@ -139,24 +227,43 @@ void DuffsDevice() { void Exceptions() { #pragma acc parallel for(int i = 0; i < 5; ++i) { - throw 5; // expected-error{{invalid throw out of OpenACC Compute Construct}} + throw 5; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} + } + +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + throw 5; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} } #pragma acc parallel for(int i = 0; i < 5; ++i) { - throw; // expected-error{{invalid throw out of OpenACC Compute Construct}} + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} + } + +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} } #pragma acc serial for(int i = 0; i < 5; ++i) { - throw; // expected-error{{invalid throw out of OpenACC Compute Construct}} + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} + } + +#pragma acc serial loop + for(int i = 0; i < 5; ++i) { + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} } #pragma acc kernels for(int i = 0; i < 5; ++i) { - throw; // expected-error{{invalid throw out of OpenACC Compute Construct}} + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} } +#pragma acc kernels loop + for(int i = 0; i < 5; ++i) { + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} + } #pragma acc parallel for(int i = 0; i < 5; ++i) { @@ -166,6 +273,14 @@ void Exceptions() { } } +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + try { + throw 5; + } catch(float f) { + } + } + #pragma acc parallel for(int i = 0; i < 5; ++i) { try { @@ -174,6 +289,14 @@ void Exceptions() { } } +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + try { + throw 5; + } catch(int f) { + } + } + #pragma acc parallel for(int i = 0; i < 5; ++i) { try { @@ -181,6 +304,15 @@ void Exceptions() { } catch(...) { } } + +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + try { + throw 5; + } catch(...) { + } + } + #pragma acc parallel for(int i = 0; i < 5; ++i) { try { @@ -189,12 +321,28 @@ void Exceptions() { } } +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + try { + throw; + } catch(...) { + } + } + #pragma acc parallel for(int i = 0; i < 5; ++i) { try { throw; } catch(...) { - throw; // expected-error{{invalid throw out of OpenACC Compute Construct}} + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} + } + } +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + try { + throw; + } catch(...) { + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} } } #pragma acc parallel @@ -202,7 +350,15 @@ void Exceptions() { try { throw; } catch(int f) { - throw; // expected-error{{invalid throw out of OpenACC Compute Construct}} + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} + } + } +#pragma acc parallel loop + for(int i = 0; i < 5; ++i) { + try { + throw; + } catch(int f) { + throw; // expected-error{{invalid throw out of OpenACC Compute/Combined Construct}} } } } diff --git a/clang/test/SemaOpenCL/access-qualifier.cl b/clang/test/SemaOpenCL/access-qualifier.cl index 726253c0b1a23246df90938af1b9d9a6773a08c1..d1c9b5e35af6cd3aeb7719bf7d1412be6e87661f 100644 --- a/clang/test/SemaOpenCL/access-qualifier.cl +++ b/clang/test/SemaOpenCL/access-qualifier.cl @@ -36,7 +36,7 @@ void myRead(read_only image1d_t); #if (__OPENCL_C_VERSION__ == 200) || ((__OPENCL_CPP_VERSION__ == 202100 || __OPENCL_C_VERSION__ == 300) && defined(__opencl_c_read_write_images)) void myReadWrite(read_write image1d_t); #else -void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' can not be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}} +void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' cannot be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}} #endif @@ -94,9 +94,9 @@ kernel void k11(read_only write_only image1d_t i){} // expected-error{{multiple kernel void k12(read_only read_only image1d_t i){} // expected-warning {{duplicate 'read_only' declaration specifier}} #if (__OPENCL_C_VERSION__ == 200) || ((__OPENCL_CPP_VERSION__ == 202100 || __OPENCL_C_VERSION__ == 300) && defined(__opencl_c_read_write_images)) -kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}} +kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' cannot be used for 'read_only pipe int'}} #else -kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}} +kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' cannot be used for '__read_write image1d_t' prior to OpenCL C version 2.0 or in version 3.0 and without __opencl_c_read_write_images feature}} #endif #if defined(__OPENCL_C_VERSION__) && __OPENCL_C_VERSION__ < 200 @@ -116,7 +116,7 @@ kernel void k14(read_only pipe int p) { kernel void pipe_ro_twice(read_only read_only pipe int i){} // expected-warning{{duplicate 'read_only' declaration specifier}} // Conflicting access qualifiers -kernel void pipe_ro_twice_tw(read_write read_only read_only pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'read_only pipe int'}} +kernel void pipe_ro_twice_tw(read_write read_only read_only pipe int i){} // expected-error{{access qualifier 'read_write' cannot be used for 'read_only pipe int'}} kernel void pipe_ro_wo(read_only write_only pipe int i){} // expected-error{{multiple access qualifiers}} typedef read_only pipe int ROPipeInt; diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx950-param.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx950-param.cl new file mode 100644 index 0000000000000000000000000000000000000000..4af67763c40dd26ef0b8fdf9f4a260a43ed8a7db --- /dev/null +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx950-param.cl @@ -0,0 +1,28 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx950 -verify -S -o - %s + +typedef float float4 __attribute__((ext_vector_type(4))); +typedef float float16 __attribute__((ext_vector_type(16))); +typedef half half8 __attribute__((ext_vector_type(8))); +typedef __bf16 bfloat8 __attribute__((ext_vector_type(8))); + + +void test_mfma_f32_16x16x32_f16(__global float4* out, half8 a, half8 b, float4 c, int X) { + + *out = __builtin_amdgcn_mfma_f32_16x16x32_f16(a, b, c, X, 0, 0); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_16x16x32_f16' must be a constant integer}} + *out = __builtin_amdgcn_mfma_f32_16x16x32_f16(a, b, c, 0, X, 0); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_16x16x32_f16' must be a constant integer}} + *out = __builtin_amdgcn_mfma_f32_16x16x32_f16(a, b, c, 0, 0, X); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_16x16x32_f16' must be a constant integer}} +} + + +void test_mfma_f32_32x32x16_f16(__global float16* out, half8 a, half8 b, float16 c, int X) { + *out = __builtin_amdgcn_mfma_f32_32x32x16_f16(a, b, c, X, 0, 0); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_32x32x16_f16' must be a constant integer}} + *out = __builtin_amdgcn_mfma_f32_32x32x16_f16(a, b, c, 0, X, 0); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_32x32x16_f16' must be a constant integer}} + *out = __builtin_amdgcn_mfma_f32_32x32x16_f16(a, b, c, 0, 0, X); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_32x32x16_f16' must be a constant integer}} +} + +void test_mfma_f32_32x32x16_bf16(__global float16* out, bfloat8 a, bfloat8 b, float16 c, int X) { + *out = __builtin_amdgcn_mfma_f32_32x32x16_bf16(a, b, c, X, 0, 0); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_32x32x16_bf16' must be a constant integer}} + *out = __builtin_amdgcn_mfma_f32_32x32x16_bf16(a, b, c, 0, X, 0); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_32x32x16_bf16' must be a constant integer}} + *out = __builtin_amdgcn_mfma_f32_32x32x16_bf16(a, b, c, 0, 0, X); // expected-error{{argument to '__builtin_amdgcn_mfma_f32_32x32x16_bf16' must be a constant integer}} +} diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx950.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx950.cl new file mode 100644 index 0000000000000000000000000000000000000000..e0fd2aa5c58a0260a9cd83465815f06ae441a6d3 --- /dev/null +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx950.cl @@ -0,0 +1,15 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx940 -verify -S -o - %s + +typedef float float4 __attribute__((ext_vector_type(4))); +typedef float float16 __attribute__((ext_vector_type(16))); +typedef half half8 __attribute__((ext_vector_type(8))); +typedef __bf16 bfloat8 __attribute__((ext_vector_type(8))); + +void test(__global float4* out0, half8 a0, half8 b0, float4 c0, + __global float16* out1, half8 a1, half8 b1, float16 c1, + __global float16* out2, bfloat8 a2, bfloat8 b2, float16 c2) { + *out0 = __builtin_amdgcn_mfma_f32_16x16x32_f16(a0, b0, c0, 0, 0, 0); // expected-error{{'__builtin_amdgcn_mfma_f32_16x16x32_f16' needs target feature gfx950-insts}} + *out1 = __builtin_amdgcn_mfma_f32_32x32x16_f16(a1, b1, c1, 0, 0, 0); // expected-error{{'__builtin_amdgcn_mfma_f32_32x32x16_f16' needs target feature gfx950-insts}} + *out2 = __builtin_amdgcn_mfma_f32_32x32x16_bf16(a2, b2, c2, 0, 0, 0); // expected-error{{'__builtin_amdgcn_mfma_f32_32x32x16_bf16' needs target feature gfx950-insts}} +} diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index 4d3469aba4bb8dad5a8741b3ab6c799eced2a417..7e7934d5fe0f5f959222e20157a38c2f7db695eb 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -210,6 +210,9 @@ config.substitutions.append( config.substitutions.append(("%host_cc", config.host_cc)) config.substitutions.append(("%host_cxx", config.host_cxx)) +# Determine whether the test target is compatible with execution on the host. +if "aarch64" in config.host_arch: + config.available_features.add("aarch64-host") # Plugins (loadable modules) if config.has_plugins and config.llvm_plugin_ext: diff --git a/clang/tools/amdgpu-arch/AMDGPUArch.cpp b/clang/tools/amdgpu-arch/AMDGPUArch.cpp index 7ae57b7877e1feedc6270f922d7501aa5417015d..6c10cbc5c46a83b8a9c03ba5889d3371a56b36e4 100644 --- a/clang/tools/amdgpu-arch/AMDGPUArch.cpp +++ b/clang/tools/amdgpu-arch/AMDGPUArch.cpp @@ -25,7 +25,7 @@ static void PrintVersion(raw_ostream &OS) { OS << clang::getClangToolFullVersion("amdgpu-arch") << '\n'; } -int printGPUsByHSA(); +int printGPUsByKFD(); int printGPUsByHIP(); int main(int argc, char *argv[]) { @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) { } #ifndef _WIN32 - if (!printGPUsByHSA()) + if (!printGPUsByKFD()) return 0; #endif diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp deleted file mode 100644 index 432f2c414ed244aac34d025bd942b26ab9a5285e..0000000000000000000000000000000000000000 --- a/clang/tools/amdgpu-arch/AMDGPUArchByHSA.cpp +++ /dev/null @@ -1,122 +0,0 @@ -//===- AMDGPUArchByHSA.cpp - list AMDGPU installed ------*- 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 implements a tool for detecting name of AMDGPU installed in system -// using HSA on Linux. This tool is used by AMDGPU OpenMP and HIP driver. -// -//===----------------------------------------------------------------------===// - -#include "clang/Basic/Version.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include - -using namespace llvm; - -typedef enum { - HSA_STATUS_SUCCESS = 0x0, -} hsa_status_t; - -typedef enum { - HSA_DEVICE_TYPE_CPU = 0, - HSA_DEVICE_TYPE_GPU = 1, -} hsa_device_type_t; - -typedef enum { - HSA_AGENT_INFO_NAME = 0, - HSA_AGENT_INFO_DEVICE = 17, -} hsa_agent_info_t; - -typedef struct hsa_agent_s { - uint64_t handle; -} hsa_agent_t; - -hsa_status_t (*hsa_init)(); -hsa_status_t (*hsa_shut_down)(); -hsa_status_t (*hsa_agent_get_info)(hsa_agent_t, hsa_agent_info_t, void *); -hsa_status_t (*hsa_iterate_agents)(hsa_status_t (*)(hsa_agent_t, void *), - void *); - -constexpr const char *DynamicHSAPath = "libhsa-runtime64.so"; - -llvm::Error loadHSA() { - std::string ErrMsg; - auto DynlibHandle = std::make_unique( - llvm::sys::DynamicLibrary::getPermanentLibrary(DynamicHSAPath, &ErrMsg)); - if (!DynlibHandle->isValid()) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Failed to 'dlopen' %s", DynamicHSAPath); - } -#define DYNAMIC_INIT(SYMBOL) \ - { \ - void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ - if (!SymbolPtr) \ - return llvm::createStringError(llvm::inconvertibleErrorCode(), \ - "Failed to 'dlsym' " #SYMBOL); \ - SYMBOL = reinterpret_cast(SymbolPtr); \ - } - DYNAMIC_INIT(hsa_init); - DYNAMIC_INIT(hsa_shut_down); - DYNAMIC_INIT(hsa_agent_get_info); - DYNAMIC_INIT(hsa_iterate_agents); -#undef DYNAMIC_INIT - return llvm::Error::success(); -} - -static hsa_status_t iterateAgentsCallback(hsa_agent_t Agent, void *Data) { - hsa_device_type_t DeviceType; - hsa_status_t Status = - hsa_agent_get_info(Agent, HSA_AGENT_INFO_DEVICE, &DeviceType); - - // continue only if device type if GPU - if (Status != HSA_STATUS_SUCCESS || DeviceType != HSA_DEVICE_TYPE_GPU) { - return Status; - } - - std::vector *GPUs = - static_cast *>(Data); - char GPUName[64]; - Status = hsa_agent_get_info(Agent, HSA_AGENT_INFO_NAME, GPUName); - if (Status != HSA_STATUS_SUCCESS) { - return Status; - } - GPUs->push_back(GPUName); - return HSA_STATUS_SUCCESS; -} - -int printGPUsByHSA() { - // Attempt to load the HSA runtime. - if (llvm::Error Err = loadHSA()) { - logAllUnhandledErrors(std::move(Err), llvm::errs()); - return 1; - } - - hsa_status_t Status = hsa_init(); - if (Status != HSA_STATUS_SUCCESS) { - return 1; - } - - std::vector GPUs; - Status = hsa_iterate_agents(iterateAgentsCallback, &GPUs); - if (Status != HSA_STATUS_SUCCESS) { - return 1; - } - - for (const auto &GPU : GPUs) - llvm::outs() << GPU << '\n'; - - if (GPUs.size() < 1) - return 1; - - hsa_shut_down(); - return 0; -} diff --git a/clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp b/clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94ebf9073e00e8c418f441dd4d5dbebc28eec0fa --- /dev/null +++ b/clang/tools/amdgpu-arch/AMDGPUArchByKFD.cpp @@ -0,0 +1,77 @@ +//===- AMDGPUArchByKFD.cpp - list AMDGPU installed ------*- 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 implements a tool for detecting name of AMD GPUs installed in +// system using the Linux sysfs interface for the AMD KFD driver. This file does +// not respect ROCR_VISIBLE_DEVICES like the ROCm environment would. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include + +using namespace llvm; + +constexpr static const char *KFD_SYSFS_NODE_PATH = + "/sys/devices/virtual/kfd/kfd/topology/nodes"; + +// See the ROCm implementation for how this is handled. +// https://github.com/ROCm/ROCT-Thunk-Interface/blob/master/src/libhsakmt.h#L126 +constexpr static long getMajor(long Ver) { return (Ver / 10000) % 100; } +constexpr static long getMinor(long Ver) { return (Ver / 100) % 100; } +constexpr static long getStep(long Ver) { return Ver % 100; } + +int printGPUsByKFD() { + SmallVector> Devices; + std::error_code EC; + for (sys::fs::directory_iterator Begin(KFD_SYSFS_NODE_PATH, EC), End; + Begin != End; Begin.increment(EC)) { + if (EC) + return 1; + + long Node = 0; + if (sys::path::stem(Begin->path()).consumeInteger(10, Node)) + return 1; + + SmallString<0> Path(Begin->path()); + sys::path::append(Path, "properties"); + + ErrorOr> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Path); + if (std::error_code EC = BufferOrErr.getError()) + return 1; + + long GFXVersion = 0; + for (line_iterator Lines(**BufferOrErr, false); !Lines.is_at_end(); + ++Lines) { + StringRef Line(*Lines); + if (Line.consume_front("gfx_target_version")) { + if (Line.drop_while([](char C) { return std::isspace(C); }) + .consumeInteger(10, GFXVersion)) + return 1; + break; + } + } + + // If this is zero the node is a CPU. + if (GFXVersion == 0) + continue; + Devices.emplace_back(Node, GFXVersion); + } + + // Sort the devices by their node to make sure it prints in order. + llvm::sort(Devices, [](auto &L, auto &R) { return L.first < R.first; }); + for (const auto &[Node, GFXVersion] : Devices) + std::fprintf(stdout, "gfx%ld%ld%lx\n", getMajor(GFXVersion), + getMinor(GFXVersion), getStep(GFXVersion)); + + return 0; +} diff --git a/clang/tools/amdgpu-arch/CMakeLists.txt b/clang/tools/amdgpu-arch/CMakeLists.txt index 1657c70125130890359adb5fe26112862fdd473c..c4c8de614565a716613165e8d0cfc94afb20dfb2 100644 --- a/clang/tools/amdgpu-arch/CMakeLists.txt +++ b/clang/tools/amdgpu-arch/CMakeLists.txt @@ -8,6 +8,6 @@ set(LLVM_LINK_COMPONENTS Support) -add_clang_tool(amdgpu-arch AMDGPUArch.cpp AMDGPUArchByHSA.cpp AMDGPUArchByHIP.cpp) +add_clang_tool(amdgpu-arch AMDGPUArch.cpp AMDGPUArchByKFD.cpp AMDGPUArchByHIP.cpp) target_link_libraries(amdgpu-arch PRIVATE clangBasic) diff --git a/clang/tools/c-index-test/core_main.cpp b/clang/tools/c-index-test/core_main.cpp index c43bff2196211825297dfe2ad5cda11c3fb48a3a..327a77a09408baa5a44cf9b8b0cd6ad2ed7f7c83 100644 --- a/clang/tools/c-index-test/core_main.cpp +++ b/clang/tools/c-index-test/core_main.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -219,8 +220,9 @@ static bool printSourceSymbols(const char *Executable, SmallVector ArgsWithProgName; ArgsWithProgName.push_back(Executable); ArgsWithProgName.append(Args.begin(), Args.end()); - IntrusiveRefCntPtr - Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); + IntrusiveRefCntPtr Diags( + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + new DiagnosticOptions)); CreateInvocationOptions CIOpts; CIOpts.Diags = Diags; CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed? @@ -273,7 +275,8 @@ static bool printSourceSymbolsFromModule(StringRef modulePath, auto HSOpts = std::make_shared(); IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + new DiagnosticOptions()); std::unique_ptr AU = ASTUnit::LoadFromASTFile(modulePath, *pchRdr, ASTUnit::LoadASTOnly, Diags, FileSystemOpts, HSOpts, /*LangOpts=*/nullptr, diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index 2473e16a546dc0b371aaaa32098968b35957af79..41a8a63a2e22bea8fb6944a63b686e04b454c6e4 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -31,6 +31,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Error.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Host.h" #include @@ -164,7 +165,8 @@ std::unique_ptr BuildCompilerInstance() { auto Ins = std::make_unique(); auto DC = std::make_unique(); const bool ShouldOwnClient = true; - Ins->createDiagnostics(DC.release(), ShouldOwnClient); + Ins->createDiagnostics(*llvm::vfs::getRealFileSystem(), DC.release(), + ShouldOwnClient); auto Inv = std::make_unique(); diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 308e5285e325789b6fbbe21f14e6505cf9dba3c9..ce6240b1b56f1ef10d5bbb844b76614480cc64e9 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -113,7 +113,7 @@ static bool run(ArrayRef Args, const char *ProgName) { // Set up compilation. std::unique_ptr CI(new CompilerInstance()); CI->setFileManager(FM.get()); - CI->createDiagnostics(); + CI->createDiagnostics(FM->getVirtualFileSystem()); if (!CI->hasDiagnostics()) return EXIT_FAILURE; diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index 9b30799c3ab263d2f7d4d6a8b89d26207c701cfd..58b56dcfd3becef9a7fd0ed9e0bcc9691ec192a3 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/ThreadPool.h" #include "llvm/Support/Threading.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Host.h" #include #include @@ -424,7 +425,8 @@ public: IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions{}; TextDiagnosticPrinter DiagConsumer(ErrOS, &*DiagOpts); IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(&*DiagOpts, &DiagConsumer, + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + &*DiagOpts, &DiagConsumer, /*ShouldOwnClient=*/false); for (auto &&M : Modules) @@ -739,7 +741,8 @@ getCompilationDatabase(int argc, char **argv, std::string &ErrorMessage) { tooling::JSONCommandLineSyntax::AutoDetect); llvm::IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions); + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + new DiagnosticOptions); driver::Driver TheDriver(CommandLine[0], llvm::sys::getDefaultTargetTriple(), *Diags); TheDriver.setCheckInputsExist(false); diff --git a/clang/tools/clang-shlib/CMakeLists.txt b/clang/tools/clang-shlib/CMakeLists.txt index 298d3a9d18fec8c7fbedfa926c91a26f9963ca90..d83c13fd394f430cc8280aaadbf21610a21e1601 100644 --- a/clang/tools/clang-shlib/CMakeLists.txt +++ b/clang/tools/clang-shlib/CMakeLists.txt @@ -48,6 +48,14 @@ add_clang_library(clang-cpp ${_OBJECTS} LINK_LIBS ${_DEPS}) + +configure_file(simple_version_script.map.in simple_version_script.map) + +if (NOT APPLE AND NOT MSVC AND NOT MINGW AND NOT LLVM_LINKER_IS_SOLARISLD) + # Solaris ld does not accept global: *; so there is no way to version *all* global symbols + target_link_options(clang-cpp PRIVATE LINKER:--version-script,${CMAKE_CURRENT_BINARY_DIR}/simple_version_script.map) +endif() + # Optimize function calls for default visibility definitions to avoid PLT and # reduce dynamic relocations. if (NOT APPLE AND NOT MINGW AND NOT LLVM_LINKER_IS_SOLARISLD_ILLUMOS) diff --git a/clang/tools/clang-shlib/simple_version_script.map.in b/clang/tools/clang-shlib/simple_version_script.map.in new file mode 100644 index 0000000000000000000000000000000000000000..cb2306d1f596828d081e33e3c5c8e6cef181864d --- /dev/null +++ b/clang/tools/clang-shlib/simple_version_script.map.in @@ -0,0 +1 @@ +@LLVM_SHLIB_SYMBOL_VERSION@ { global: *; }; diff --git a/clang/tools/diagtool/ShowEnabledWarnings.cpp b/clang/tools/diagtool/ShowEnabledWarnings.cpp index 66a295db054c3535c7788c6a40c294c7deb44dde..48bed7c828c16bb154525af6ca8d459d902ddb86 100644 --- a/clang/tools/diagtool/ShowEnabledWarnings.cpp +++ b/clang/tools/diagtool/ShowEnabledWarnings.cpp @@ -14,6 +14,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/VirtualFileSystem.h" DEF_DIAGTOOL("show-enabled", "Show which warnings are enabled for a given command line", @@ -74,7 +75,8 @@ createDiagnostics(unsigned int argc, char **argv) { // Build the diagnostics parser IntrusiveRefCntPtr FinalDiags = - CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts()); + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + &Invocation->getDiagnosticOpts()); if (!FinalDiags) return nullptr; diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index 554dc956c7cfe32fca138a5f2a4e89c2941912d6..d14058ff2c723d48ba0a937587cbcf8c9daed16d 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -45,6 +45,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/TargetParser/AArch64TargetParser.h" @@ -264,7 +265,7 @@ int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { CompilerInvocation::GetResourcesPath(Argv0, MainAddr); // Create the actual diagnostics engine. - Clang->createDiagnostics(); + Clang->createDiagnostics(*llvm::vfs::getRealFileSystem()); if (!Clang->hasDiagnostics()) return 1; diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 98afabfdceff3cc6451fc4c243275e2292f71286..263439aa1fff990a44b22594202a6c99bd679cda 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -59,6 +59,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/Threading.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/thread.h" #include @@ -2183,6 +2184,7 @@ public: void VisitCXXParenListInitExpr(const CXXParenListInitExpr *E); void VisitOpenACCComputeConstruct(const OpenACCComputeConstruct *D); void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *D); + void VisitOpenACCCombinedConstruct(const OpenACCCombinedConstruct *D); void VisitOMPExecutableDirective(const OMPExecutableDirective *D); void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D); void VisitOMPLoopDirective(const OMPLoopDirective *D); @@ -3637,6 +3639,13 @@ void EnqueueVisitor::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *C) { EnqueueChildren(Clause); } +void EnqueueVisitor::VisitOpenACCCombinedConstruct( + const OpenACCCombinedConstruct *C) { + EnqueueChildren(C); + for (auto *Clause : C->clauses()) + EnqueueChildren(Clause); +} + void EnqueueVisitor::VisitAnnotateAttr(const AnnotateAttr *A) { EnqueueChildren(A); } @@ -4142,7 +4151,8 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx, auto HSOpts = std::make_shared(); IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + new DiagnosticOptions()); std::unique_ptr AU = ASTUnit::LoadFromASTFile( ast_filename, CXXIdx->getPCHContainerOperations()->getRawReader(), ASTUnit::LoadEverything, Diags, FileSystemOpts, HSOpts, @@ -4215,7 +4225,8 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename, std::unique_ptr DiagOpts = CreateAndPopulateDiagOpts( llvm::ArrayRef(command_line_args, num_command_line_args)); IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(DiagOpts.release())); + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + DiagOpts.release())); if (options & CXTranslationUnit_KeepGoing) Diags->setFatalsAsError(true); @@ -6403,6 +6414,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("OpenACCComputeConstruct"); case CXCursor_OpenACCLoopConstruct: return cxstring::createRef("OpenACCLoopConstruct"); + case CXCursor_OpenACCCombinedConstruct: + return cxstring::createRef("OpenACCCombinedConstruct"); } llvm_unreachable("Unhandled CXCursorKind"); diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index bfcb908b5169a4faf978c87d0cb69ce5af951964..2158ea171a3f0d36e404f692dc7e90719badffd3 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -894,6 +894,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::OpenACCLoopConstructClass: K = CXCursor_OpenACCLoopConstruct; break; + case Stmt::OpenACCCombinedConstructClass: + K = CXCursor_OpenACCCombinedConstruct; + break; case Stmt::OMPTargetParallelGenericLoopDirectiveClass: K = CXCursor_OMPTargetParallelGenericLoopDirective; break; diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 05d88452209fb38aef79c7e37210d160d64dedc0..b890921972a0a7b4fb370536e5a1ad8f607c4cb4 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -29,6 +29,7 @@ #include "clang/Lex/PreprocessorOptions.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/VirtualFileSystem.h" #include #include #include @@ -479,10 +480,10 @@ static CXErrorCode clang_indexSourceFile_Impl( CaptureDiag = new CaptureDiagnosticConsumer(); // Configure the diagnostics. - IntrusiveRefCntPtr - Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, - CaptureDiag, - /*ShouldOwnClient=*/true)); + IntrusiveRefCntPtr Diags( + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + new DiagnosticOptions, CaptureDiag, + /*ShouldOwnClient=*/true)); // Recover resources if we crash before exiting this function. llvm::CrashRecoveryContextCleanupRegistrar @@ -28,8 +28,8 @@ typedef std::map VarInfoMap; /// \brief Records information on variable initializers to a map. class EvaluateConstantInitializersVisitor - : public clang::RecursiveASTVisitor { - public: + : public clang::DynamicRecursiveASTVisitor { +public: explicit EvaluateConstantInitializersVisitor(VarInfoMap &VarInfo) : VarInfo(VarInfo) {} @@ -38,7 +38,7 @@ class EvaluateConstantInitializersVisitor /// /// For each VarDecl with an initializer this also records in VarInfo /// whether the initializer could be evaluated as a constant. - bool VisitVarDecl(const clang::VarDecl *VD) { + bool VisitVarDecl(clang::VarDecl *VD) override { if (const clang::Expr *Init = VD->getInit()) { clang::Expr::EvalResult Result; bool WasEvaluated = Init->EvaluateAsRValue(Result, VD->getASTContext()); @@ -109,9 +109,9 @@ TEST(EvaluateAsRValue, FailsGracefullyForUnknownTypes) { } class CheckLValueToRValueConversionVisitor - : public clang::RecursiveASTVisitor { + : public clang::DynamicRecursiveASTVisitor { public: - bool VisitDeclRefExpr(const clang::DeclRefExpr *E) { + bool VisitDeclRefExpr(clang::DeclRefExpr *E) override { clang::Expr::EvalResult Result; E->EvaluateAsRValue(Result, E->getDecl()->getASTContext(), true); diff --git a/clang/unittests/AST/ExternalASTSourceTest.cpp b/clang/unittests/AST/ExternalASTSourceTest.cpp index 8b70be664e043c05a9dfd8440a9b2b5083ea2cc8..8e1bde1247f66019ec0eb0f0ccfea9661b4a5f52 100644 --- a/clang/unittests/AST/ExternalASTSourceTest.cpp +++ b/clang/unittests/AST/ExternalASTSourceTest.cpp @@ -10,13 +10,14 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/ExternalASTSource.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ExternalASTSource.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" using namespace clang; @@ -46,7 +47,7 @@ private: bool testExternalASTSource(ExternalASTSource *Source, StringRef FileContents) { CompilerInstance Compiler; - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); auto Invocation = std::make_shared(); Invocation->getPreprocessorOpts().addRemappedFile( diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index e994086c99d041922586f0006f346eea6a4e8454..7cf52df9b14d05490ade9a517abed71746dec3e3 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -134,8 +134,8 @@ struct StructuralEquivalenceTest : ::testing::Test { bool testStructuralMatch(Decl *D0, Decl *D1, bool IgnoreTemplateParmDepth = false) { - llvm::DenseSet> NonEquivalentDecls01; - llvm::DenseSet> NonEquivalentDecls10; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10; StructuralEquivalenceContext Ctx01( D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls01, StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false, @@ -153,8 +153,8 @@ struct StructuralEquivalenceTest : ::testing::Test { } bool testStructuralMatch(StmtWithASTContext S0, StmtWithASTContext S1) { - llvm::DenseSet> NonEquivalentDecls01; - llvm::DenseSet> NonEquivalentDecls10; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10; StructuralEquivalenceContext Ctx01( *S0.Context, *S1.Context, NonEquivalentDecls01, StructuralEquivalenceKind::Default, false, false); @@ -1792,7 +1792,7 @@ TEST_F( EXPECT_FALSE(testStructuralMatch(t)); } struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest { - llvm::DenseSet> NonEquivalentDecls; + StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls; template std::pair @@ -1804,8 +1804,10 @@ struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest { } template - bool isInNonEqCache(std::pair D) { - return NonEquivalentDecls.count(D) > 0; + bool isInNonEqCache(std::pair D, + bool IgnoreTemplateParmDepth = false) { + return NonEquivalentDecls.count( + std::make_tuple(D.first, D.second, IgnoreTemplateParmDepth)) > 0; } }; @@ -2015,6 +2017,78 @@ TEST_F(StructuralEquivalenceCacheTest, Cycle) { findDeclPair(TU, functionDecl(hasName("x"))))); } +TEST_F(StructuralEquivalenceCacheTest, TemplateParmDepth) { + // In 'friend struct Y' ClassTemplateDecl has the TU as parent context. + // This declaration has template depth 1 (it is already inside a template). + // It has not a previous declaration and is an "undeclared" friend. + // + // Second TU has a specialization of 'struct X'. + // In this case 'friend struct Y' has the ClassTemplateSpecializationDecl as + // parent. It has template depth 0 (it is in the specialization). It has the + // first 'struct Y' declaration as previous declaration and canonical + // declaration. + // + // When these two 'friend struct Y' are compared, only the template depth is + // different. + // FIXME: Structural equivalence checks the depth only in types, not in + // TemplateParmDecl. For this reason the second 'A1' argument is needed (as a + // type) in the template to make the check fail. + auto TU = makeTuDecls( + R"( + template + struct Y; + + template + struct X { + template + friend struct Y; + }; + )", + R"( + template + struct Y; + + template + struct X { + template + friend struct Y; + }; + + X x; + )", + Lang_CXX03); + + auto *D0 = LastDeclMatcher().match( + get<0>(TU), classTemplateDecl(hasName("Y"), unless(isImplicit()))); + auto *D1 = LastDeclMatcher().match( + get<1>(TU), classTemplateDecl(hasName("Y"), unless(isImplicit()))); + ASSERT_EQ(D0->getTemplateDepth(), 1u); + ASSERT_EQ(D1->getTemplateDepth(), 0u); + + StructuralEquivalenceContext Ctx_NoIgnoreTemplateParmDepth( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false, + false, false); + + EXPECT_FALSE(Ctx_NoIgnoreTemplateParmDepth.IsEquivalent(D0, D1)); + + Decl *NonEqDecl0 = + D0->getCanonicalDecl()->getTemplateParameters()->getParam(1); + Decl *NonEqDecl1 = + D1->getCanonicalDecl()->getTemplateParameters()->getParam(1); + EXPECT_TRUE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), false)); + EXPECT_FALSE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), true)); + + StructuralEquivalenceContext Ctx_IgnoreTemplateParmDepth( + get<0>(TU)->getASTContext(), get<1>(TU)->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, false, false, + false, true); + + EXPECT_TRUE(Ctx_IgnoreTemplateParmDepth.IsEquivalent(D0, D1)); + + EXPECT_FALSE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), true)); +} + struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {}; /// Fallback matcher to be used only when there is no specific matcher for a diff --git a/clang/unittests/Analysis/CloneDetectionTest.cpp b/clang/unittests/Analysis/CloneDetectionTest.cpp index 738f6efd2018d77733520848fe987b0a9a5b107c..d0148a8c28c54ed0e85c2dbd860d48b6585fb79b 100644 --- a/clang/unittests/Analysis/CloneDetectionTest.cpp +++ b/clang/unittests/Analysis/CloneDetectionTest.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/CloneDetection.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" @@ -15,15 +15,14 @@ namespace clang { namespace analysis { namespace { -class CloneDetectionVisitor - : public RecursiveASTVisitor { +class CloneDetectionVisitor : public DynamicRecursiveASTVisitor { CloneDetector &Detector; public: explicit CloneDetectionVisitor(CloneDetector &D) : Detector(D) {} - bool VisitFunctionDecl(FunctionDecl *D) { + bool VisitFunctionDecl(FunctionDecl *D) override { Detector.analyzeCodeBody(D); return true; } diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h index 891489cb511a4fb47450960276551c545ae0f9cd..931c75effbf75442e40c7b53ad435a508c1a99ba 100644 --- a/clang/unittests/CodeGen/TestCompiler.h +++ b/clang/unittests/CodeGen/TestCompiler.h @@ -20,6 +20,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Host.h" namespace llvm { @@ -35,7 +36,7 @@ struct TestCompiler { clang::CodeGenOptions CGO = clang::CodeGenOptions()) { compiler.getLangOpts() = LO; compiler.getCodeGenOpts() = CGO; - compiler.createDiagnostics(); + compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple()); llvm::Triple Tr(TrStr); diff --git a/clang/unittests/Driver/DXCModeTest.cpp b/clang/unittests/Driver/DXCModeTest.cpp index 2a079a62f1bc13f5a56431f9e8e114b0243b82d7..616c07c0d389d12a2303b6de2dc7b0cf90d5d5c9 100644 --- a/clang/unittests/Driver/DXCModeTest.cpp +++ b/clang/unittests/Driver/DXCModeTest.cpp @@ -219,7 +219,8 @@ TEST(DxcModeTest, DefaultEntry) { const char *Args[] = {"clang", "--driver-mode=dxc", "-Tcs_6_7", "foo.hlsl"}; IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); + CompilerInstance::createDiagnostics(*InMemoryFileSystem, + new DiagnosticOptions()); CreateInvocationOptions CIOpts; CIOpts.Diags = Diags; diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index bdb65fab43565f2f977c7184b53d1dafa03c94eb..275f3c6c1c517565f6e66a187be270bcf6303eb9 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -580,7 +580,7 @@ TEST(CompilerInvocation, SplitSwarfSingleCrash) { TEST(ToolChainTest, UEFICallingConventionTest) { clang::CompilerInstance compiler; - compiler.createDiagnostics(); + compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); std::string TrStr = "x86_64-unknown-uefi"; llvm::Triple Tr(TrStr); diff --git a/clang/unittests/Format/FormatTestVerilog.cpp b/clang/unittests/Format/FormatTestVerilog.cpp index 49d276fc78d81b4f18e1023f99f01c2578579cf6..e4a14ff754d1a2851e9c7467a0f89fc20f77e863 100644 --- a/clang/unittests/Format/FormatTestVerilog.cpp +++ b/clang/unittests/Format/FormatTestVerilog.cpp @@ -702,6 +702,18 @@ TEST_F(FormatTestVerilog, Hierarchy) { " generate\n" " endgenerate\n" "endfunction : x"); + // Type names with '::' should be recognized. + verifyFormat("function automatic x::x x\n" + " (input x);\n" + "endfunction : x"); + // Names having to do macros should be recognized. + verifyFormat("function automatic x::x x``x\n" + " (input x);\n" + "endfunction : x"); + verifyFormat("function automatic x::x `x\n" + " (input x);\n" + "endfunction : x"); + verifyNoCrash("x x(x x, x x);"); } TEST_F(FormatTestVerilog, Identifiers) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index bb8ee416ea2db5cd49a71aac38dfe8407a95536b..e1ae1770e8ebe8cde131254c27ee5bef5cac4223 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2598,6 +2598,20 @@ TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) { Tokens = Annotate("x = '{\"\"};"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[4], tok::string_literal, TT_Unknown); + + // Module headers. + Tokens = Annotate("module x();\nendmodule"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_VerilogMultiLineListLParen); + Tokens = Annotate("function automatic `x x();\nendmodule"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_VerilogMultiLineListLParen); + Tokens = Annotate("function automatic x``x x();\nendmodule"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_VerilogMultiLineListLParen); + Tokens = Annotate("function automatic x::x x();\nendmodule"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_VerilogMultiLineListLParen); } TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) { diff --git a/clang/unittests/Frontend/ASTUnitTest.cpp b/clang/unittests/Frontend/ASTUnitTest.cpp index bd5d5d009818079d2106dadbaee3a1e41e745d4e..e6524a019871dc1526d4dae9afa16c5c1a9c2e80 100644 --- a/clang/unittests/Frontend/ASTUnitTest.cpp +++ b/clang/unittests/Frontend/ASTUnitTest.cpp @@ -17,6 +17,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" using namespace llvm; @@ -41,17 +42,18 @@ protected: const char *Args[] = {"clang", "-xc++", InputFileName.c_str()}; - Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + auto VFS = llvm::vfs::getRealFileSystem(); + Diags = CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions()); CreateInvocationOptions CIOpts; CIOpts.Diags = Diags; + CIOpts.VFS = VFS; CInvok = createInvocation(Args, std::move(CIOpts)); if (!CInvok) return nullptr; - FileManager *FileMgr = - new FileManager(FileSystemOptions(), vfs::getRealFileSystem()); + FileManager *FileMgr = new FileManager(FileSystemOptions(), VFS); PCHContainerOps = std::make_shared(); return ASTUnit::LoadFromCompilerInvocation( @@ -134,7 +136,8 @@ TEST_F(ASTUnitTest, ModuleTextualHeader) { const char *Args[] = {"clang", "test.cpp", "-fmodule-map-file=m.modulemap", "-fmodule-name=M"}; - Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + Diags = + CompilerInstance::createDiagnostics(*InMemoryFs, new DiagnosticOptions()); CreateInvocationOptions CIOpts; CIOpts.Diags = Diags; CInvok = createInvocation(Args, std::move(CIOpts)); @@ -162,7 +165,8 @@ TEST_F(ASTUnitTest, LoadFromCommandLineEarlyError) { const char *Args[] = {"clang", "-target", "foobar", InputFileName.c_str()}; - auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + auto Diags = CompilerInstance::createDiagnostics( + *llvm::vfs::getRealFileSystem(), new DiagnosticOptions()); auto PCHContainerOps = std::make_shared(); std::unique_ptr ErrUnit; @@ -189,7 +193,8 @@ TEST_F(ASTUnitTest, LoadFromCommandLineWorkingDirectory) { const char *Args[] = {"clang", "-working-directory", WorkingDir.c_str(), InputFileName.c_str()}; - auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + auto Diags = CompilerInstance::createDiagnostics( + *llvm::vfs::getRealFileSystem(), new DiagnosticOptions()); auto PCHContainerOps = std::make_shared(); std::unique_ptr ErrUnit; diff --git a/clang/unittests/Frontend/CodeGenActionTest.cpp b/clang/unittests/Frontend/CodeGenActionTest.cpp index a6520910c83996bcffe3a1d73166e5c4ef205979..d855302ed0542940499d3ebdce17adb58b2eea9f 100644 --- a/clang/unittests/Frontend/CodeGenActionTest.cpp +++ b/clang/unittests/Frontend/CodeGenActionTest.cpp @@ -16,6 +16,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/PreprocessorOptions.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" using namespace llvm; @@ -52,7 +53,7 @@ TEST(CodeGenTest, TestNullCodeGen) { Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler; Compiler.setInvocation(std::move(Invocation)); - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); EXPECT_TRUE(Compiler.hasDiagnostics()); std::unique_ptr Act(new NullCodeGenAction); @@ -70,7 +71,7 @@ TEST(CodeGenTest, CodeGenFromIRMemBuffer) { Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler; Compiler.setInvocation(std::move(Invocation)); - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); EXPECT_TRUE(Compiler.hasDiagnostics()); EmitLLVMOnlyAction Action; @@ -101,7 +102,7 @@ TEST(CodeGenTest, DebugInfoCWDCodeGen) { SmallString<256> IRBuffer; Compiler.setOutputStream(std::make_unique(IRBuffer)); Compiler.setInvocation(std::move(Invocation)); - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*VFS); Compiler.createFileManager(std::move(VFS)); EmitLLVMAction Action; diff --git a/clang/unittests/Frontend/CompilerInstanceTest.cpp b/clang/unittests/Frontend/CompilerInstanceTest.cpp index 5cf548e913cc10184c8d39b0b131d2418715feb7..07329eb299e293848f14a1bebf2b1b58b19a010e 100644 --- a/clang/unittests/Frontend/CompilerInstanceTest.cpp +++ b/clang/unittests/Frontend/CompilerInstanceTest.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" using namespace llvm; @@ -53,7 +54,8 @@ TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) { const char *Args[] = {"clang", VFSArg.c_str(), "-xc++", "-"}; IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); + CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), + new DiagnosticOptions()); CreateInvocationOptions CIOpts; CIOpts.Diags = Diags; @@ -87,8 +89,9 @@ TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) { auto DiagPrinter = std::make_unique( DiagnosticsOS, new DiagnosticOptions()); CompilerInstance Instance; - IntrusiveRefCntPtr Diags = Instance.createDiagnostics( - DiagOpts, DiagPrinter.get(), /*ShouldOwnClient=*/false); + IntrusiveRefCntPtr Diags = + Instance.createDiagnostics(*llvm::vfs::getRealFileSystem(), DiagOpts, + DiagPrinter.get(), /*ShouldOwnClient=*/false); Diags->Report(diag::err_expected) << "no crash"; ASSERT_EQ(DiagnosticOutput, "error: expected no crash\n"); diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp index 45478de5e6f7c8a2583acfcfd61965104aa99a98..4ff6824f1e21e3d274c60750185855f1c9160496 100644 --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -12,6 +12,7 @@ #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/ModuleFileExtension.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Host.h" #include "gmock/gmock.h" @@ -38,9 +39,9 @@ public: } CommandLineTest() - : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(), - new TextDiagnosticBuffer())) { - } + : Diags(CompilerInstance::createDiagnostics( + *llvm::vfs::getRealFileSystem(), new DiagnosticOptions(), + new TextDiagnosticBuffer())) {} }; template diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 818e8cef27e51bc52271cb23ebb1815554f1aff2..75e166767c6678915c16dcbd6f4a22958d1f0935 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -9,7 +9,7 @@ #include "clang/Frontend/FrontendAction.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/LangStandard.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" @@ -20,6 +20,7 @@ #include "clang/Serialization/InMemoryModuleCache.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Triple.h" #include "gtest/gtest.h" @@ -53,7 +54,7 @@ public: } private: - class Visitor : public ASTConsumer, public RecursiveASTVisitor { + class Visitor : public ASTConsumer, public DynamicRecursiveASTVisitor { public: Visitor(CompilerInstance &CI, bool ActOnEndOfTranslationUnit, std::vector &decl_names) : @@ -67,7 +68,7 @@ private: TraverseDecl(context.getTranslationUnitDecl()); } - virtual bool VisitNamedDecl(NamedDecl *Decl) { + bool VisitNamedDecl(NamedDecl *Decl) override { decl_names_.push_back(Decl->getQualifiedNameAsString()); return true; } @@ -90,7 +91,7 @@ TEST(ASTFrontendAction, Sanity) { invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance compiler; compiler.setInvocation(std::move(invocation)); - compiler.createDiagnostics(); + compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); TestASTFrontendAction test_action; ASSERT_TRUE(compiler.ExecuteAction(test_action)); @@ -110,7 +111,7 @@ TEST(ASTFrontendAction, IncrementalParsing) { invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance compiler; compiler.setInvocation(std::move(invocation)); - compiler.createDiagnostics(); + compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true); ASSERT_TRUE(compiler.ExecuteAction(test_action)); @@ -137,7 +138,7 @@ TEST(ASTFrontendAction, LateTemplateIncrementalParsing) { invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance compiler; compiler.setInvocation(std::move(invocation)); - compiler.createDiagnostics(); + compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true, /*actOnEndOfTranslationUnit=*/true); @@ -183,7 +184,7 @@ TEST(PreprocessorFrontendAction, EndSourceFile) { Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; CompilerInstance Compiler; Compiler.setInvocation(std::move(Invocation)); - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); TestPPCallbacks *Callbacks = new TestPPCallbacks; TestPPCallbacksFrontendAction TestAction(Callbacks); @@ -245,7 +246,8 @@ TEST(ASTFrontendAction, ExternalSemaSource) { CompilerInstance Compiler; Compiler.setInvocation(std::move(Invocation)); auto *TDC = new TypoDiagnosticConsumer; - Compiler.createDiagnostics(TDC, /*ShouldOwnClient=*/true); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem(), TDC, + /*ShouldOwnClient=*/true); Compiler.setExternalSemaSource(new TypoExternalSemaSource(Compiler)); SyntaxOnlyAction TestAction; @@ -277,7 +279,7 @@ TEST(GeneratePCHFrontendAction, CacheGeneratedPCH) { Invocation->getTargetOpts().Triple = "x86_64-apple-darwin19.0.0"; CompilerInstance Compiler; Compiler.setInvocation(std::move(Invocation)); - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); GeneratePCHAction TestAction; ASSERT_TRUE(Compiler.ExecuteAction(TestAction)); diff --git a/clang/unittests/Frontend/OutputStreamTest.cpp b/clang/unittests/Frontend/OutputStreamTest.cpp index 2618558c7e11eef1a4d4ab3b3e3e90c605937ee9..fa5d726d252903d4fa8ec578a0322232867b8e53 100644 --- a/clang/unittests/Frontend/OutputStreamTest.cpp +++ b/clang/unittests/Frontend/OutputStreamTest.cpp @@ -13,6 +13,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/FrontendTool/Utils.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/Support/VirtualFileSystem.h" #include "gtest/gtest.h" using namespace llvm; @@ -37,7 +38,7 @@ TEST(FrontendOutputTests, TestOutputStream) { Compiler.setOutputStream(std::move(IRStream)); Compiler.setInvocation(std::move(Invocation)); - Compiler.createDiagnostics(); + Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); bool Success = ExecuteCompilerInvocation(&Compiler); EXPECT_TRUE(Success); @@ -62,6 +63,7 @@ TEST(FrontendOutputTests, TestVerboseOutputStreamShared) { Compiler.setInvocation(std::move(Invocation)); IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); Compiler.createDiagnostics( + *llvm::vfs::getRealFileSystem(), new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true); Compiler.setVerboseOutputStream(VerboseStream); @@ -91,6 +93,7 @@ TEST(FrontendOutputTests, TestVerboseOutputStreamOwned) { Compiler.setInvocation(std::move(Invocation)); IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); Compiler.createDiagnostics( + *llvm::vfs::getRealFileSystem(), new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true); Compiler.setVerboseOutputStream(std::move(VerboseStream)); diff --git a/clang/unittests/Frontend/PCHPreambleTest.cpp b/clang/unittests/Frontend/PCHPreambleTest.cpp index 2ce24c91ac0f133c6d13124ed2249e652fc7f861..58ec2e2ce70589382e56cc9681ad2cfd68c068fa 100644 --- a/clang/unittests/Frontend/PCHPreambleTest.cpp +++ b/clang/unittests/Frontend/PCHPreambleTest.cpp @@ -94,8 +94,9 @@ public: PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); PPOpts.RemappedFilesKeepOriginalName = true; - IntrusiveRefCntPtr - Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, new DiagnosticConsumer)); + IntrusiveRefCntPtr Diags( + CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions, + new DiagnosticConsumer)); FileManager *FileMgr = new FileManager(FSOpts, VFS); diff --git a/clang/unittests/Frontend/ReparseWorkingDirTest.cpp b/clang/unittests/Frontend/ReparseWorkingDirTest.cpp index ca7ce23dd64b2294f6b272cfc7272341cdcc3ec9..b0f2d51b80b9e797ebc8fe392cb097e2e278b40a 100644 --- a/clang/unittests/Frontend/ReparseWorkingDirTest.cpp +++ b/clang/unittests/Frontend/ReparseWorkingDirTest.cpp @@ -58,7 +58,7 @@ public: CI->getTargetOpts().Triple = "i386-unknown-linux-gnu"; IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(new DiagnosticOptions, + CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions, new DiagnosticConsumer)); FileManager *FileMgr = new FileManager(CI->getFileSystemOpts(), VFS); diff --git a/clang/unittests/Frontend/UtilsTest.cpp b/clang/unittests/Frontend/UtilsTest.cpp index ae014d3f86b5aa571a0ed6d2d8bdee676a3ed167..304fbe2a8e69f053d06b74f9697c61fdd9313146 100644 --- a/clang/unittests/Frontend/UtilsTest.cpp +++ b/clang/unittests/Frontend/UtilsTest.cpp @@ -28,9 +28,9 @@ TEST(BuildCompilerInvocationTest, RecoverMultipleJobs) { clang::IgnoringDiagConsumer D; CreateInvocationOptions Opts; Opts.RecoverOnError = true; - Opts.Diags = clang::CompilerInstance::createDiagnostics(new DiagnosticOptions, - &D, false); Opts.VFS = new llvm::vfs::InMemoryFileSystem(); + Opts.Diags = clang::CompilerInstance::createDiagnostics( + *Opts.VFS, new DiagnosticOptions, &D, false); std::unique_ptr CI = createInvocation(Args, Opts); ASSERT_TRUE(CI); EXPECT_THAT(CI->TargetOpts->Triple, testing::StartsWith("i386-")); @@ -46,7 +46,7 @@ TEST(BuildCompilerInvocationTest, ProbePrecompiled) { clang::IgnoringDiagConsumer D; llvm::IntrusiveRefCntPtr CommandLineDiagsEngine = - clang::CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, + clang::CompilerInstance::createDiagnostics(*FS, new DiagnosticOptions, &D, false); // Default: ProbePrecompiled=false CreateInvocationOptions CIOpts; diff --git a/clang/unittests/Sema/SemaNoloadLookupTest.cpp b/clang/unittests/Sema/SemaNoloadLookupTest.cpp index cf89c7331e4e0fd06c7ecaccae56fdf74294f86a..a8e1bb0bd2c5de52c37ad79eab1443c4ac4c446a 100644 --- a/clang/unittests/Sema/SemaNoloadLookupTest.cpp +++ b/clang/unittests/Sema/SemaNoloadLookupTest.cpp @@ -57,11 +57,12 @@ public: std::string FileName = llvm::Twine(ModuleName + ".cppm").str(); addFile(FileName, Contents); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; + CIOpts.VFS = llvm::vfs::getRealFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, + new DiagnosticOptions()); CIOpts.Diags = Diags; - CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); std::string CacheBMIPath = llvm::Twine(TestDir + "/" + ModuleName + ".pcm").str(); diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp index ad8892b8c8be1e055baec762886b9e29e29d41c4..6a839d1bf9350b329d97bbaf8b8b3a87a2b50941 100644 --- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp +++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp @@ -63,12 +63,14 @@ export int aa = 43; std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str(); { - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; - CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, + new DiagnosticOptions()); + CIOpts.Diags = Diags; + const char *Args[] = {"clang++", "-std=c++20", "--precompile", "-working-directory", TestDir.c_str(), "a.cppm"}; @@ -103,11 +105,12 @@ export int aa = 43; } { - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; - CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, + new DiagnosticOptions()); + CIOpts.Diags = Diags; std::string BMIPath = llvm::Twine(TestDir + "/a.pcm").str(); const char *Args[] = { diff --git a/clang/unittests/Serialization/ModuleCacheTest.cpp b/clang/unittests/Serialization/ModuleCacheTest.cpp index a7ca98549b41250f2502ce00f792ad4a20837902..6ceee1c6536cb5806a811d680e2b8e7bb0681a3e 100644 --- a/clang/unittests/Serialization/ModuleCacheTest.cpp +++ b/clang/unittests/Serialization/ModuleCacheTest.cpp @@ -106,11 +106,11 @@ TEST_F(ModuleCacheTest, CachedModuleNewPath) { SmallString<256> MCPArg("-fmodules-cache-path="); MCPArg.append(ModuleCachePath); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; - CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, new DiagnosticOptions()); + CIOpts.Diags = Diags; // First run should pass with no errors const char *Args[] = {"clang", "-fmodules", "-Fframeworks", @@ -156,11 +156,11 @@ TEST_F(ModuleCacheTest, CachedModuleNewPathAllowErrors) { SmallString<256> MCPArg("-fmodules-cache-path="); MCPArg.append(ModuleCachePath); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; - CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, new DiagnosticOptions()); + CIOpts.Diags = Diags; // First run should pass with no errors const char *Args[] = {"clang", "-fmodules", "-Fframeworks", diff --git a/clang/unittests/Serialization/NoCommentsTest.cpp b/clang/unittests/Serialization/NoCommentsTest.cpp index a0a564aeff9a15e43006da6593ca009bc12f9294..a1fb23404e4154fc7014d247bd0e2dc917e355de 100644 --- a/clang/unittests/Serialization/NoCommentsTest.cpp +++ b/clang/unittests/Serialization/NoCommentsTest.cpp @@ -83,11 +83,11 @@ export module Comments; void foo() {} )cpp"); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; - CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, new DiagnosticOptions()); + CIOpts.Diags = Diags; std::string CacheBMIPath = llvm::Twine(TestDir + "/Comments.pcm").str(); const char *Args[] = {"clang++", "-std=c++20", diff --git a/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp b/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp index d26e1cb633654f678294138ccedab5dc19f3ee51..cf317eddb0f373fa627eec0ec8fda2128e2c3187 100644 --- a/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp +++ b/clang/unittests/Serialization/PreambleInNamedModulesTest.cpp @@ -75,10 +75,10 @@ export using ::E; )cpp", MainFilePath); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); IntrusiveRefCntPtr VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions()); CreateInvocationOptions CIOpts; CIOpts.Diags = Diags; diff --git a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp index 5cbbfb9ff003b377063703322f7b1e220f8751d4..14c0c30add2078d023afed58a7f2ceb535477899 100644 --- a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp +++ b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp @@ -90,11 +90,11 @@ export namespace Fibonacci } )cpp"); - IntrusiveRefCntPtr Diags = - CompilerInstance::createDiagnostics(new DiagnosticOptions()); CreateInvocationOptions CIOpts; - CIOpts.Diags = Diags; CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); + IntrusiveRefCntPtr Diags = + CompilerInstance::createDiagnostics(*CIOpts.VFS, new DiagnosticOptions()); + CIOpts.Diags = Diags; const char *Args[] = {"clang++", "-std=c++20", "--precompile", "-working-directory", diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp index 339b470153e64ed9334c0d3e6b45fb4231e93d2a..995ebf625b7ab2e6cf40d173f0e3b191ece78877 100644 --- a/clang/unittests/Support/TimeProfilerTest.cpp +++ b/clang/unittests/Support/TimeProfilerTest.cpp @@ -45,8 +45,6 @@ std::string teardownProfiler() { // We only parse AST here. This is enough for constexpr evaluation. bool compileFromString(StringRef Code, StringRef Standard, StringRef File, llvm::StringMap Headers = {}) { - CompilerInstance Compiler; - Compiler.createDiagnostics(); llvm::IntrusiveRefCntPtr FS( new llvm::vfs::InMemoryFileSystem()); @@ -57,6 +55,8 @@ bool compileFromString(StringRef Code, StringRef Standard, StringRef File, } llvm::IntrusiveRefCntPtr Files( new FileManager(FileSystemOptions(), FS)); + CompilerInstance Compiler; + Compiler.createDiagnostics(Files->getVirtualFileSystem()); Compiler.setFileManager(Files.get()); auto Invocation = std::make_shared(); diff --git a/clang/unittests/Tooling/ASTSelectionTest.cpp b/clang/unittests/Tooling/ASTSelectionTest.cpp index 113165f68449ca2874ab7f7939937746138f0959..1897bc15196ec25837602da923c9d8234fb9203e 100644 --- a/clang/unittests/Tooling/ASTSelectionTest.cpp +++ b/clang/unittests/Tooling/ASTSelectionTest.cpp @@ -26,7 +26,7 @@ struct FileLocation { using FileRange = std::pair; -class SelectionFinderVisitor : public TestVisitor { +class SelectionFinderVisitor : public TestVisitor { FileLocation Location; std::optional SelectionRange; llvm::function_refgetASTContext(); const SourceManager &SM = Context.getSourceManager(); diff --git a/clang/unittests/Tooling/CRTPTestVisitor.h b/clang/unittests/Tooling/CRTPTestVisitor.h new file mode 100644 index 0000000000000000000000000000000000000000..67ae36b2e3ddd9204edce06f1c1bb33c62ef6e91 --- /dev/null +++ b/clang/unittests/Tooling/CRTPTestVisitor.h @@ -0,0 +1,42 @@ +//===--- TestVisitor.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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines a CRTP-based RecursiveASTVisitor helper for tests. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H +#define LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H + +#include "TestVisitor.h" +#include "clang/AST/RecursiveASTVisitor.h" + +// CRTP versions of the visitors in TestVisitor.h. +namespace clang { +template +class CRTPTestVisitor : public RecursiveASTVisitor, + public detail::TestVisitorHelper { +public: + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + + void InvokeTraverseDecl(TranslationUnitDecl *D) override { + RecursiveASTVisitor::TraverseDecl(D); + } +}; + +template +class CRTPExpectedLocationVisitor + : public CRTPTestVisitor, + public detail::ExpectedLocationVisitorHelper { + ASTContext *getASTContext() override { return this->Context; } +}; +} // namespace clang + +#endif // LLVM_CLANG_UNITTESTS_TOOLING_CRTPTESTVISITOR_H diff --git a/clang/unittests/Tooling/CastExprTest.cpp b/clang/unittests/Tooling/CastExprTest.cpp index eab23a5a98e5d519b253a0f5e5a996665e570561..e5a8d994bf011ba93d250aaff146a67839589e08 100644 --- a/clang/unittests/Tooling/CastExprTest.cpp +++ b/clang/unittests/Tooling/CastExprTest.cpp @@ -12,17 +12,17 @@ using namespace clang; namespace { -struct CastExprVisitor : TestVisitor { +struct CastExprVisitor : TestVisitor { std::function OnExplicitCast; std::function OnCast; - bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) { + bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) override { if (OnExplicitCast) OnExplicitCast(Expr); return true; } - bool VisitCastExpr(CastExpr *Expr) { + bool VisitCastExpr(CastExpr *Expr) override { if (OnCast) OnCast(Expr); return true; diff --git a/clang/unittests/Tooling/CommentHandlerTest.cpp b/clang/unittests/Tooling/CommentHandlerTest.cpp index 7eb11ccd6ee2d1524b79066d4e0814b68af91914..edfb72e2ec599b308424cbb8f27528132857d4b2 100644 --- a/clang/unittests/Tooling/CommentHandlerTest.cpp +++ b/clang/unittests/Tooling/CommentHandlerTest.cpp @@ -22,12 +22,9 @@ struct Comment { class CommentVerifier; typedef std::vector CommentList; -class CommentHandlerVisitor : public TestVisitor, - public CommentHandler { - typedef TestVisitor base; - +class CommentHandlerVisitor : public TestVisitor, public CommentHandler { public: - CommentHandlerVisitor() : base(), PP(nullptr), Verified(false) {} + CommentHandlerVisitor() : PP(nullptr), Verified(false) {} ~CommentHandlerVisitor() override { EXPECT_TRUE(Verified) << "CommentVerifier not accessed"; @@ -64,7 +61,7 @@ private: CommentList Comments; bool Verified; - class CommentHandlerAction : public base::TestAction { + class CommentHandlerAction : public TestAction { public: CommentHandlerAction(CommentHandlerVisitor *Visitor) : TestAction(Visitor) { } diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp index ec0e143be4a209169c9484fa910fcf8c5a063547..e1c4770805992065a970449d8a2907617a872fc6 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp @@ -60,7 +60,8 @@ public: Compiler.setInvocation(std::move(Invocation)); Compiler.setFileManager(FileMgr); - Compiler.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false); + Compiler.createDiagnostics(FileMgr->getVirtualFileSystem(), DiagConsumer, + /*ShouldOwnClient=*/false); if (!Compiler.hasDiagnostics()) return false; diff --git a/clang/unittests/Tooling/ExecutionTest.cpp b/clang/unittests/Tooling/ExecutionTest.cpp index 91ab8594f6823d6a56bee3d4db84fa8771a4468e..b0fd7ccb950ff483c2daed43a4fb7e44460be459 100644 --- a/clang/unittests/Tooling/ExecutionTest.cpp +++ b/clang/unittests/Tooling/ExecutionTest.cpp @@ -9,7 +9,7 @@ #include "clang/Tooling/Execution.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" @@ -30,12 +30,9 @@ namespace { // This traverses the AST and outputs function name as key and "1" as value for // each function declaration. -class ASTConsumerWithResult - : public ASTConsumer, - public RecursiveASTVisitor { +class ASTConsumerWithResult : public ASTConsumer, + public DynamicRecursiveASTVisitor { public: - using ASTVisitor = RecursiveASTVisitor; - explicit ASTConsumerWithResult(ExecutionContext *Context) : Context(Context) { assert(Context != nullptr); } @@ -44,12 +41,12 @@ public: TraverseDecl(Context.getTranslationUnitDecl()); } - bool TraverseFunctionDecl(clang::FunctionDecl *Decl) { + bool TraverseFunctionDecl(clang::FunctionDecl *Decl) override { Context->reportResult(Decl->getNameAsString(), Context->getRevision() + ":" + Context->getCorpus() + ":" + Context->getCurrentCompilationUnit() + "/1"); - return ASTVisitor::TraverseFunctionDecl(Decl); + return DynamicRecursiveASTVisitor::TraverseFunctionDecl(Decl); } private: diff --git a/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp b/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp index 5d16595aec8014e114b75463df371ed74a5a5283..b167eb4b8117555b04827464fe842c412db6d24f 100644 --- a/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp +++ b/clang/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp @@ -44,13 +44,14 @@ private: llvm::SmallVector TraversalStack; }; -class DummyMatchVisitor : public ExpectedLocationVisitor { +class DummyMatchVisitor : public ExpectedLocationVisitor { bool EmitDeclIndices, EmitStmtIndices; public: DummyMatchVisitor(bool EmitDeclIndices = false, bool EmitStmtIndices = false) : EmitDeclIndices(EmitDeclIndices), EmitStmtIndices(EmitStmtIndices) {} - bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) { + + bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) override { const ASTContext &Context = TU->getASTContext(); const SourceManager &SM = Context.getSourceManager(); LexicallyOrderedDeclVisitor SubVisitor(*this, SM, EmitDeclIndices, diff --git a/clang/unittests/Tooling/LookupTest.cpp b/clang/unittests/Tooling/LookupTest.cpp index 2cf5ebb2a4cbd02c204d99c7a26f606951bd73fd..acd1714a26e071ef8a783bf806ca86a78067d7fe 100644 --- a/clang/unittests/Tooling/LookupTest.cpp +++ b/clang/unittests/Tooling/LookupTest.cpp @@ -13,31 +13,31 @@ using namespace clang; namespace { -struct GetDeclsVisitor : TestVisitor { +struct GetDeclsVisitor : TestVisitor { std::function OnCall; std::function OnRecordTypeLoc; std::function OnUsingTypeLoc; SmallVector DeclStack; - bool VisitCallExpr(CallExpr *Expr) { + bool VisitCallExpr(CallExpr *Expr) override { if (OnCall) OnCall(Expr); return true; } - bool VisitRecordTypeLoc(RecordTypeLoc Loc) { + bool VisitRecordTypeLoc(RecordTypeLoc Loc) override { if (OnRecordTypeLoc) OnRecordTypeLoc(Loc); return true; } - bool VisitUsingTypeLoc(UsingTypeLoc Loc) { + bool VisitUsingTypeLoc(UsingTypeLoc Loc) override { if (OnUsingTypeLoc) OnUsingTypeLoc(Loc); return true; } - bool TraverseDecl(Decl *D) { + bool TraverseDecl(Decl *D) override { DeclStack.push_back(D); bool Ret = TestVisitor::TraverseDecl(D); DeclStack.pop_back(); diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp index 686d189cf69eb2fdf6221f9971edf161c292ca8f..5ded64d4fcc8c5080bface2ebb093a09d1bc6df2 100644 --- a/clang/unittests/Tooling/QualTypeNamesTest.cpp +++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp @@ -11,12 +11,12 @@ using namespace clang; namespace { -struct TypeNameVisitor : TestVisitor { +struct TypeNameVisitor : TestVisitor { llvm::StringMap ExpectedQualTypeNames; bool WithGlobalNsPrefix = false; // ValueDecls are the least-derived decl with both a qualtype and a name. - bool VisitValueDecl(const ValueDecl *VD) { + bool VisitValueDecl(ValueDecl *VD) override { std::string ExpectedName = ExpectedQualTypeNames.lookup(VD->getNameAsString()); if (ExpectedName != "") { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp index d72a110d37e0fdcbf2b959b2380424541b17ccd3..eed016e9ee7c24e0159e2b424bb0ed008019d420 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp @@ -12,12 +12,12 @@ using namespace clang; namespace { -class VarDeclVisitor : public ExpectedLocationVisitor { +class VarDeclVisitor : public ExpectedLocationVisitor { public: - bool VisitVarDecl(VarDecl *Variable) { - Match(Variable->getNameAsString(), Variable->getBeginLoc()); - return true; - } + bool VisitVarDecl(VarDecl *Variable) override { + Match(Variable->getNameAsString(), Variable->getBeginLoc()); + return true; + } }; TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) { @@ -29,12 +29,11 @@ TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) { VarDeclVisitor::Lang_CXX11)); } -class ParmVarDeclVisitorForImplicitCode : - public ExpectedLocationVisitor { +class ParmVarDeclVisitorForImplicitCode : public ExpectedLocationVisitor { public: - bool shouldVisitImplicitCode() const { return true; } + ParmVarDeclVisitorForImplicitCode() { ShouldVisitImplicitCode = true; } - bool VisitParmVarDecl(ParmVarDecl *ParamVar) { + bool VisitParmVarDecl(ParmVarDecl *ParamVar) override { Match(ParamVar->getNameAsString(), ParamVar->getBeginLoc()); return true; } @@ -58,10 +57,9 @@ TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) { "void bar(Y a) {Y b = a;}")); } -class NamedDeclVisitor - : public ExpectedLocationVisitor { +class NamedDeclVisitor : public ExpectedLocationVisitor { public: - bool VisitNamedDecl(NamedDecl *Decl) { + bool VisitNamedDecl(NamedDecl *Decl) override { std::string NameWithTemplateArgs; llvm::raw_string_ostream OS(NameWithTemplateArgs); Decl->getNameForDiagnostic(OS, diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp index 8ac0604c09110ad0d173e1b2ba2038df9449bd88..481559ed08efdffad233e4bbca9453ef2a54d80e 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTestPostOrderVisitor.cpp @@ -11,14 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; namespace { - -class RecordingVisitor : public TestVisitor { - +class RecordingVisitor : public CRTPTestVisitor { bool VisitPostOrder; public: diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp index a21186265db6a90cbfa42208815573b67f78bdab..eec628ca3964175a235541717f4bc27429a2ffd9 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp @@ -12,9 +12,9 @@ using namespace clang; namespace { -class TypeLocVisitor : public ExpectedLocationVisitor { +class TypeLocVisitor : public ExpectedLocationVisitor { public: - bool VisitTypeLoc(TypeLoc TypeLocation) { + bool VisitTypeLoc(TypeLoc TypeLocation) override { Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp index 022ef8b8322868c43eb0d605a73a16125aed9fac..7693e77236b0c4c726dcb8d8a178d216b457f408 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Attr.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; @@ -14,7 +14,7 @@ namespace { // Check to ensure that attributes and expressions within them are being // visited. -class AttrVisitor : public ExpectedLocationVisitor { +class AttrVisitor : public CRTPExpectedLocationVisitor { public: bool VisitMemberExpr(MemberExpr *ME) { Match(ME->getMemberDecl()->getNameAsString(), ME->getBeginLoc()); @@ -30,7 +30,6 @@ public: } }; - TEST(RecursiveASTVisitor, AttributesAreVisited) { AttrVisitor Visitor; Visitor.ExpectMatch("Attr", 4, 24); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp index c11e726fe8552849cfcd93ac45dfad4bd5a0ec4a..c1217179768ac2b881ef30806a1d68a3a232e327 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/BitfieldInitializer.cpp @@ -14,10 +14,9 @@ using namespace clang; namespace { // Check to ensure that bitfield initializers are visited. -class BitfieldInitializerVisitor - : public ExpectedLocationVisitor { +class BitfieldInitializerVisitor : public ExpectedLocationVisitor { public: - bool VisitIntegerLiteral(IntegerLiteral *IL) { + bool VisitIntegerLiteral(IntegerLiteral *IL) override { Match(std::to_string(IL->getValue().getSExtValue()), IL->getLocation()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp index 1fb192dcda0863071212ddba3d7c40fae2e65255..4b0c4c31f2dd2e2d2a571f22a5af82128432c15b 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp @@ -12,10 +12,9 @@ using namespace clang; namespace { -class CXXBoolLiteralExprVisitor - : public ExpectedLocationVisitor { +class CXXBoolLiteralExprVisitor : public ExpectedLocationVisitor { public: - bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) { + bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) override { if (BE->getValue()) Match("true", BE->getLocation()); else diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp index c7b31e06e0e8e9640d92bcaeb42900cf33f294b2..fe95e8987a73a1748aa911c420e241ba526066cd 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMemberCall.cpp @@ -12,10 +12,9 @@ using namespace clang; namespace { -class CXXMemberCallVisitor - : public ExpectedLocationVisitor { +class CXXMemberCallVisitor : public ExpectedLocationVisitor { public: - bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) { + bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) override { Match(Call->getMethodDecl()->getQualifiedNameAsString(), Call->getBeginLoc()); return true; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp index 90fa84bd448124c93cb5404f7b86bfe61b28b894..1eeb3df81a3168e25d8192204a26429537c1ce65 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp @@ -13,25 +13,21 @@ using namespace clang; namespace { -class CXXMethodDeclVisitor - : public ExpectedLocationVisitor { +class CXXMethodDeclVisitor : public ExpectedLocationVisitor { public: - CXXMethodDeclVisitor(bool VisitImplicitCode) - : VisitImplicitCode(VisitImplicitCode) {} - - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } + CXXMethodDeclVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + } - bool VisitDeclRefExpr(DeclRefExpr *D) { + bool VisitDeclRefExpr(DeclRefExpr *D) override { Match("declref", D->getLocation()); return true; } - bool VisitParmVarDecl(ParmVarDecl *P) { + + bool VisitParmVarDecl(ParmVarDecl *P) override { Match("parm", P->getLocation()); return true; } - -private: - bool VisitImplicitCode; }; TEST(RecursiveASTVisitor, CXXMethodDeclNoDefaultBodyVisited) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp index 376874eb351de12ec0618d6ed1f9d98f443e1ae5..46686199c05d4ecfa1ac77781e072022f4c13b79 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp @@ -12,15 +12,13 @@ using namespace clang; namespace { -class CXXOperatorCallExprTraverser - : public ExpectedLocationVisitor { +class CXXOperatorCallExprTraverser : public ExpectedLocationVisitor { public: // Use Traverse, not Visit, to check that data recursion optimization isn't // bypassing the call of this function. - bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) { + bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) override { Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc()); - return ExpectedLocationVisitor:: - TraverseCXXOperatorCallExpr(CE); + return ExpectedLocationVisitor::TraverseCXXOperatorCallExpr(CE); } }; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h index 92e30c2d46e5faa83e837a06bdc695f5a3be44a7..355ecfb452e7e84f81a47571dcb494e3130aed11 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCommon.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; @@ -21,7 +21,7 @@ enum class ShouldTraversePostOrder : bool { /// sequence of calls to user-defined callbacks like Traverse*(), WalkUp*(), /// Visit*(). template -class RecordingVisitorBase : public TestVisitor { +class RecordingVisitorBase : public CRTPTestVisitor { ShouldTraversePostOrder ShouldTraversePostOrderValue; public: diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp index 3ea5abd46a1eca51388a918fb3b2f3171b89d701..79dc84b2fdb7b9be5fe12f4889cf97b3322843e3 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Class.cpp @@ -14,10 +14,11 @@ namespace { // Checks for lambda classes that are not marked as implicitly-generated. // (There should be none.) -class ClassVisitor : public ExpectedLocationVisitor { +class ClassVisitor : public ExpectedLocationVisitor { public: ClassVisitor() : SawNonImplicitLambdaClass(false) {} - bool VisitCXXRecordDecl(CXXRecordDecl* record) { + + bool VisitCXXRecordDecl(CXXRecordDecl *record) override { if (record->isLambda() && !record->isImplicit()) SawNonImplicitLambdaClass = true; return true; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp index 6a8d91672f1d936aaddc29561b5c4c7201cf93f0..6dd28e27d7ec2cc030503288f681c09d4bbb996f 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp @@ -16,78 +16,87 @@ using namespace clang; namespace { -struct ConceptVisitor : ExpectedLocationVisitor { - bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) { +struct ConceptVisitor : ExpectedLocationVisitor { + ConceptVisitor(bool VisitImplicitCode = false) { + ShouldVisitImplicitCode = VisitImplicitCode; + } + + bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) override { ++ConceptSpecializationExprsVisited; return true; } - bool TraverseTypeConstraint(const TypeConstraint *C) { + bool TraverseTypeConstraint(const TypeConstraint *C) override { ++TypeConstraintsTraversed; return ExpectedLocationVisitor::TraverseTypeConstraint(C); } - bool TraverseConceptRequirement(concepts::Requirement *R) { + bool TraverseConceptRequirement(concepts::Requirement *R) override { ++ConceptRequirementsTraversed; return ExpectedLocationVisitor::TraverseConceptRequirement(R); } - bool TraverseConceptReference(ConceptReference *CR) { + bool TraverseConceptReference(ConceptReference *CR) override { ++ConceptReferencesTraversed; return ExpectedLocationVisitor::TraverseConceptReference(CR); } - bool VisitConceptReference(ConceptReference *CR) { + bool VisitConceptReference(ConceptReference *CR) override { ++ConceptReferencesVisited; return true; } - bool shouldVisitImplicitCode() { return ShouldVisitImplicitCode; } - int ConceptSpecializationExprsVisited = 0; int TypeConstraintsTraversed = 0; int ConceptRequirementsTraversed = 0; int ConceptReferencesTraversed = 0; int ConceptReferencesVisited = 0; - bool ShouldVisitImplicitCode = false; }; TEST(RecursiveASTVisitor, Concepts) { - ConceptVisitor Visitor; - Visitor.ShouldVisitImplicitCode = true; - EXPECT_TRUE(Visitor.runOver("template concept Fooable = true;\n" - "template void bar(T);", - ConceptVisitor::Lang_CXX2a)); - // Check that we traverse the "Fooable T" template parameter's - // TypeConstraint's ImmediatelyDeclaredConstraint, which is a - // ConceptSpecializationExpr. - EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited); - // Also check we traversed the TypeConstraint that produced the expr. - EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + { + ConceptVisitor Visitor{true}; + EXPECT_TRUE( + Visitor.runOver("template concept Fooable = true;\n" + "template void bar(T);", + ConceptVisitor::Lang_CXX2a)); + // Check that we traverse the "Fooable T" template parameter's + // TypeConstraint's ImmediatelyDeclaredConstraint, which is a + // ConceptSpecializationExpr. + EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited); + // Also check we traversed the TypeConstraint that produced the expr. + EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + } - Visitor = {}; // Don't visit implicit code now. - EXPECT_TRUE(Visitor.runOver("template concept Fooable = true;\n" - "template void bar(T);", - ConceptVisitor::Lang_CXX2a)); - // Check that we only visit the TypeConstraint, but not the implicitly - // generated immediately declared expression. - EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited); - EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + { + ConceptVisitor Visitor; // Don't visit implicit code now. + EXPECT_TRUE( + Visitor.runOver("template concept Fooable = true;\n" + "template void bar(T);", + ConceptVisitor::Lang_CXX2a)); + // Check that we only visit the TypeConstraint, but not the implicitly + // generated immediately declared expression. + EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited); + EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + } - Visitor = {}; - EXPECT_TRUE(Visitor.runOver("template concept A = true;\n" - "template struct vector {};\n" - "template concept B = requires(T x) {\n" - " typename vector;\n" - " {x} -> A;\n" - " requires true;\n" - "};", - ConceptVisitor::Lang_CXX2a)); - EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); - EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + { + ConceptVisitor Visitor; + EXPECT_TRUE( + Visitor.runOver("template concept A = true;\n" + "template struct vector {};\n" + "template concept B = requires(T x) {\n" + " typename vector;\n" + " {x} -> A;\n" + " requires true;\n" + "};", + ConceptVisitor::Lang_CXX2a)); + EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + } - Visitor = {}; + ConceptVisitor Visitor; llvm::StringRef Code = R"cpp( template concept True = false; @@ -107,34 +116,34 @@ struct Foo {}; EXPECT_EQ(2, Visitor.ConceptReferencesVisited); } -struct VisitDeclOnlyOnce : ExpectedLocationVisitor { - bool VisitConceptDecl(ConceptDecl *D) { +struct VisitDeclOnlyOnce : ExpectedLocationVisitor { + VisitDeclOnlyOnce() { ShouldWalkTypesOfTypeLocs = false; } + + bool VisitConceptDecl(ConceptDecl *D) override { ++ConceptDeclsVisited; return true; } - bool VisitAutoType(AutoType *) { + bool VisitAutoType(AutoType *) override { ++AutoTypeVisited; return true; } - bool VisitAutoTypeLoc(AutoTypeLoc) { + bool VisitAutoTypeLoc(AutoTypeLoc) override { ++AutoTypeLocVisited; return true; } - bool VisitConceptReference(ConceptReference *) { + bool VisitConceptReference(ConceptReference *) override { ++ConceptReferencesVisited; return true; } - bool TraverseVarDecl(VarDecl *V) { + bool TraverseVarDecl(VarDecl *V) override { // The base traversal visits only the `TypeLoc`. // However, in the test we also validate the underlying `QualType`. TraverseType(V->getType()); return ExpectedLocationVisitor::TraverseVarDecl(V); } - bool shouldWalkTypesOfTypeLocs() { return false; } - int ConceptDeclsVisited = 0; int AutoTypeVisited = 0; int AutoTypeLocVisited = 0; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp index b4f4f54dc7e2f92264893ed3a7113e62c60be9d8..7b2ed9715aa80d2e5702657d177bdb3925416543 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ConstructExpr.cpp @@ -18,18 +18,11 @@ namespace { /// The name recorded for the match is the name of the class whose constructor /// is invoked by the CXXConstructExpr, not the name of the class whose /// constructor the CXXConstructExpr is contained in. -class ConstructExprVisitor - : public ExpectedLocationVisitor { +class ConstructExprVisitor : public ExpectedLocationVisitor { public: - ConstructExprVisitor() : ShouldVisitImplicitCode(false) {} + ConstructExprVisitor() { ShouldVisitImplicitCode = false; } - bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } - - void setShouldVisitImplicitCode(bool NewValue) { - ShouldVisitImplicitCode = NewValue; - } - - bool VisitCXXConstructExpr(CXXConstructExpr* Expr) { + bool VisitCXXConstructExpr(CXXConstructExpr *Expr) override { if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) { if (const CXXRecordDecl* Class = Ctor->getParent()) { Match(Class->getName(), Expr->getLocation()); @@ -37,14 +30,11 @@ public: } return true; } - - private: - bool ShouldVisitImplicitCode; }; TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) { ConstructExprVisitor Visitor; - Visitor.setShouldVisitImplicitCode(true); + Visitor.ShouldVisitImplicitCode = true; Visitor.ExpectMatch("WithCtor", 2, 8); // Simple has a constructor that implicitly initializes 'w'. Test // that a visitor that visits implicit code visits that initialization. @@ -60,7 +50,7 @@ TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) { // visits are omitted when the visitor does not include implicit code. TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) { ConstructExprVisitor Visitor; - Visitor.setShouldVisitImplicitCode(false); + Visitor.ShouldVisitImplicitCode = false; Visitor.DisallowMatch("WithCtor", 2, 8); // Simple has a constructor that implicitly initializes 'w'. Test // that a visitor that skips implicit code skips that initialization. diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp index adc972e1c3d9130cbfb87c29d29fc8b73dce5b6b..6ed986c187eb525c4f4939e26078f43f8a57c1f3 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp @@ -12,23 +12,14 @@ using namespace clang; namespace { -class DeclRefExprVisitor : public ExpectedLocationVisitor { +class DeclRefExprVisitor : public ExpectedLocationVisitor { public: - DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {} + DeclRefExprVisitor() { ShouldVisitImplicitCode = false; } - bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } - - void setShouldVisitImplicitCode(bool NewValue) { - ShouldVisitImplicitCode = NewValue; - } - - bool VisitDeclRefExpr(DeclRefExpr *Reference) { + bool VisitDeclRefExpr(DeclRefExpr *Reference) override { Match(Reference->getNameInfo().getAsString(), Reference->getLocation()); return true; } - -private: - bool ShouldVisitImplicitCode; }; TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) { @@ -73,7 +64,7 @@ TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) { TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) { DeclRefExprVisitor Visitor; - Visitor.setShouldVisitImplicitCode(true); + Visitor.ShouldVisitImplicitCode = true; // We're expecting "i" to be visited twice: once for the initialization expr // for the captured variable "i" outside of the lambda body, and again for // the use of "i" inside the lambda. diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp index df878bfc113e57194919ed36480f549ddcd3dab5..7d03b283947993d47db69957c8b81d68f79ad747 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/DeductionGuide.cpp @@ -13,23 +13,20 @@ using namespace clang; namespace { -class DeductionGuideVisitor - : public ExpectedLocationVisitor { +class DeductionGuideVisitor : public ExpectedLocationVisitor { public: - DeductionGuideVisitor(bool ShouldVisitImplicitCode) - : ShouldVisitImplicitCode(ShouldVisitImplicitCode) {} - bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + DeductionGuideVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + ShouldVisitTemplateInstantiations = false; + } + + bool VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) override { std::string Storage; llvm::raw_string_ostream Stream(Storage); D->print(Stream); Match(Storage, D->getLocation()); return true; } - - bool shouldVisitTemplateInstantiations() const { return false; } - - bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; } - bool ShouldVisitImplicitCode; }; TEST(RecursiveASTVisitor, DeductionGuideNonImplicitMode) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp index 27999e5ef8efcbfc20e513b4f739f947c13c963f..dc9455a01e488293da60ec6fefc6829770dd23c7 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtor.cpp @@ -13,12 +13,9 @@ using namespace clang; namespace { // A visitor that visits implicit declarations and matches constructors. -class ImplicitCtorVisitor - : public ExpectedLocationVisitor { +class ImplicitCtorVisitor : public ExpectedLocationVisitor { public: - bool shouldVisitImplicitCode() const { return true; } - - bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) { + bool VisitCXXConstructorDecl(CXXConstructorDecl *Ctor) override { if (Ctor->isImplicit()) { // Was not written in source code if (const CXXRecordDecl* Class = Ctor->getParent()) { Match(Class->getName(), Ctor->getLocation()); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp index c762e1cffc36864b2c5a382c1bbf72274e5b4663..ae952c33bfe78b26a23172cd1b21b772bc5df2bb 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ImplicitCtorInitializer.cpp @@ -12,26 +12,20 @@ using namespace clang; namespace { -class CXXCtorInitializerVisitor - : public ExpectedLocationVisitor { +class CXXCtorInitializerVisitor : public ExpectedLocationVisitor { public: - CXXCtorInitializerVisitor(bool VisitImplicitCode) - : VisitImplicitCode(VisitImplicitCode) {} - - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } + CXXCtorInitializerVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + } - bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) override { if (!Init->isWritten()) VisitedImplicitInitializer = true; Match("initializer", Init->getSourceLocation()); - return ExpectedLocationVisitor< - CXXCtorInitializerVisitor>::TraverseConstructorInitializer(Init); + return ExpectedLocationVisitor::TraverseConstructorInitializer(Init); } bool VisitedImplicitInitializer = false; - -private: - bool VisitImplicitCode; }; // Check to ensure that CXXCtorInitializer is not visited when implicit code diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp index 80d9c9873505b47fa99a90ac23ac82c3ef4f51ae..5836fc1b2e8de544c02fdae37c5651dcf37d428c 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrder.cpp @@ -6,14 +6,14 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; namespace { class InitListExprPostOrderVisitor - : public ExpectedLocationVisitor { + : public CRTPExpectedLocationVisitor { public: bool shouldTraversePostOrder() const { return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp index 8750f78349443ebfa30033b1b3ab52453944141c..20140d2dcbf9e4321a696d4964bb34910ff21fcc 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp @@ -6,19 +6,19 @@ // //===----------------------------------------------------------------------===// -#include "TestVisitor.h" +#include "CRTPTestVisitor.h" using namespace clang; namespace { class InitListExprPostOrderNoQueueVisitor - : public ExpectedLocationVisitor { + : public CRTPExpectedLocationVisitor { public: bool shouldTraversePostOrder() const { return true; } bool TraverseInitListExpr(InitListExpr *ILE) { - return ExpectedLocationVisitor::TraverseInitListExpr(ILE); + return CRTPExpectedLocationVisitor::TraverseInitListExpr(ILE); } bool VisitInitListExpr(InitListExpr *ILE) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp index 3fa1529ea0eefec48234edc9bfbff4b126cb9dce..933d25898390ddcc33c0414ec1373bada73a2bb5 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrder.cpp @@ -14,21 +14,16 @@ namespace { // Check to ensure that InitListExpr is visited twice, once each for the // syntactic and semantic form. -class InitListExprPreOrderVisitor - : public ExpectedLocationVisitor { +class InitListExprPreOrderVisitor : public ExpectedLocationVisitor { public: - InitListExprPreOrderVisitor(bool VisitImplicitCode) - : VisitImplicitCode(VisitImplicitCode) {} - - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } + InitListExprPreOrderVisitor(bool VisitImplicitCode) { + ShouldVisitImplicitCode = VisitImplicitCode; + } - bool VisitInitListExpr(InitListExpr *ILE) { + bool VisitInitListExpr(InitListExpr *ILE) override { Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc()); return true; } - -private: - bool VisitImplicitCode; }; TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) { diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp index 8db88e1e06397576443cb12d17eba062f9c7e2cb..0dcd11b8027f04ce7c805964a5d46e58609f1923 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp @@ -12,14 +12,13 @@ using namespace clang; namespace { -class InitListExprPreOrderNoQueueVisitor - : public ExpectedLocationVisitor { +class InitListExprPreOrderNoQueueVisitor : public ExpectedLocationVisitor { public: - bool TraverseInitListExpr(InitListExpr *ILE) { + bool TraverseInitListExpr(InitListExpr *ILE) override { return ExpectedLocationVisitor::TraverseInitListExpr(ILE); } - bool VisitInitListExpr(InitListExpr *ILE) { + bool VisitInitListExpr(InitListExpr *ILE) override { Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getBeginLoc()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp index 3fc3cb1a99a744c004a92ac9b4c5cdb137f36147..83136fc11edb2c0451e4529e8132db63627ada23 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/IntegerLiteral.cpp @@ -13,10 +13,9 @@ using namespace clang; namespace { // Check to ensure that implicit default argument expressions are visited. -class IntegerLiteralVisitor - : public ExpectedLocationVisitor { +class IntegerLiteralVisitor : public ExpectedLocationVisitor { public: - bool VisitIntegerLiteral(const IntegerLiteral *IL) { + bool VisitIntegerLiteral(IntegerLiteral *IL) override { Match("literal", IL->getLocation()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp index b1d6d593e733a96cafbbca9cc5d1a30323aeb2eb..4a9175ed2dda2422c3d180f6d9b55ac8aec48d21 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaDefaultCapture.cpp @@ -13,10 +13,9 @@ using namespace clang; namespace { // Matches the (optional) capture-default of a lambda-introducer. -class LambdaDefaultCaptureVisitor - : public ExpectedLocationVisitor { +class LambdaDefaultCaptureVisitor : public ExpectedLocationVisitor { public: - bool VisitLambdaExpr(LambdaExpr *Lambda) { + bool VisitLambdaExpr(LambdaExpr *Lambda) override { if (Lambda->getCaptureDefault() != LCD_None) { Match("", Lambda->getCaptureDefaultLoc()); } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp index 337dace5fd22744c3939f464752a41f657ea8a61..0ce7f4b18762f27b89468ae65d4625c452697188 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaExpr.cpp @@ -14,9 +14,11 @@ using namespace clang; namespace { -class LambdaExprVisitor : public ExpectedLocationVisitor { +class LambdaExprVisitor : public ExpectedLocationVisitor { public: - bool VisitLambdaExpr(LambdaExpr *Lambda) { + LambdaExprVisitor() { ShouldVisitImplicitCode = false; } + + bool VisitLambdaExpr(LambdaExpr *Lambda) override { PendingBodies.push(Lambda->getBody()); PendingClasses.push(Lambda->getLambdaClass()); Match("", Lambda->getIntroducerRange().getBegin()); @@ -24,12 +26,12 @@ public: } /// For each call to VisitLambdaExpr, we expect a subsequent call to visit /// the body (and maybe the lambda class, which is implicit). - bool VisitStmt(Stmt *S) { + bool VisitStmt(Stmt *S) override { if (!PendingBodies.empty() && S == PendingBodies.top()) PendingBodies.pop(); return true; } - bool VisitDecl(Decl *D) { + bool VisitDecl(Decl *D) override { if (!PendingClasses.empty() && D == PendingClasses.top()) PendingClasses.pop(); return true; @@ -38,9 +40,6 @@ public: bool allBodiesHaveBeenTraversed() const { return PendingBodies.empty(); } bool allClassesHaveBeenTraversed() const { return PendingClasses.empty(); } - bool VisitImplicitCode = false; - bool shouldVisitImplicitCode() const { return VisitImplicitCode; } - private: std::stack PendingBodies; std::stack PendingClasses; @@ -67,7 +66,7 @@ TEST(RecursiveASTVisitor, LambdaInLambda) { TEST(RecursiveASTVisitor, TopLevelLambda) { LambdaExprVisitor Visitor; - Visitor.VisitImplicitCode = true; + Visitor.ShouldVisitImplicitCode = true; Visitor.ExpectMatch("", 1, 10); Visitor.ExpectMatch("", 1, 14); EXPECT_TRUE(Visitor.runOver("auto x = []{ [] {}; };", @@ -78,7 +77,7 @@ TEST(RecursiveASTVisitor, TopLevelLambda) { TEST(RecursiveASTVisitor, VisitsLambdaExprAndImplicitClass) { LambdaExprVisitor Visitor; - Visitor.VisitImplicitCode = true; + Visitor.ShouldVisitImplicitCode = true; Visitor.ExpectMatch("", 1, 12); EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }", LambdaExprVisitor::Lang_CXX11)); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp index c355e3f1083f966fc4da32591d3fbb6956ba98c9..cfac3a3c5ad988480e4d3442adc1a659fcbd9b2b 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp @@ -13,24 +13,23 @@ using namespace clang; namespace { // Matches (optional) explicit template parameters. -class LambdaTemplateParametersVisitor - : public ExpectedLocationVisitor { +class LambdaTemplateParametersVisitor : public ExpectedLocationVisitor { public: - bool shouldVisitImplicitCode() const { return false; } + LambdaTemplateParametersVisitor() { ShouldVisitImplicitCode = false; } - bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { + bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) override { EXPECT_FALSE(D->isImplicit()); Match(D->getName(), D->getBeginLoc()); return true; } - bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { + bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) override { EXPECT_FALSE(D->isImplicit()); Match(D->getName(), D->getBeginLoc()); return true; } - bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { + bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) override { EXPECT_FALSE(D->isImplicit()); Match(D->getName(), D->getBeginLoc()); return true; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp index d67bd0395a670eeadca21c87c73fd7a7bee13274..587a00dd27051145a51011103ef36389b97ac422 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp @@ -13,16 +13,15 @@ using namespace clang; namespace { -class MemberPointerTypeLocVisitor - : public ExpectedLocationVisitor { +class MemberPointerTypeLocVisitor : public ExpectedLocationVisitor { public: - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { if (!TL) return true; Match(TL.getDecl()->getName(), TL.getNameLoc()); return true; } - bool VisitRecordTypeLoc(RecordTypeLoc RTL) { + bool VisitRecordTypeLoc(RecordTypeLoc RTL) override { if (!RTL) return true; Match(RTL.getDecl()->getName(), RTL.getNameLoc()); diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp index 868a3988c756d2cfafd5b8b3b9c6cbe08f403574..ddc663e2b6fd3f479f97ad3499730a0af81c9587 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/NestedNameSpecifiers.cpp @@ -13,17 +13,16 @@ using namespace clang; namespace { // Check to ensure that nested name specifiers are visited. -class NestedNameSpecifiersVisitor - : public ExpectedLocationVisitor { +class NestedNameSpecifiersVisitor : public ExpectedLocationVisitor { public: - bool VisitRecordTypeLoc(RecordTypeLoc RTL) { + bool VisitRecordTypeLoc(RecordTypeLoc RTL) override { if (!RTL) return true; Match(RTL.getDecl()->getName(), RTL.getNameLoc()); return true; } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) override { if (!NNS) return true; if (const NamespaceDecl *ND = diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp index c316f98f40ce0f47964d9b5a259b56c6c5cf6097..89ccf20587ad061e146dfbc882f62c66eb9888a8 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/ParenExpr.cpp @@ -12,9 +12,9 @@ using namespace clang; namespace { -class ParenExprVisitor : public ExpectedLocationVisitor { +class ParenExprVisitor : public ExpectedLocationVisitor { public: - bool VisitParenExpr(ParenExpr *Parens) { + bool VisitParenExpr(ParenExpr *Parens) override { Match("", Parens->getExprLoc()); return true; } diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp index b87e89f3fd56ff027ddc6bf007ef7c833f9471d9..e5e743ab8d76daddda941a6c376a69e34472774a 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp @@ -12,18 +12,16 @@ using namespace clang; namespace { -class TemplateArgumentLocTraverser - : public ExpectedLocationVisitor { +class TemplateArgumentLocTraverser : public ExpectedLocationVisitor { public: - bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) override { std::string ArgStr; llvm::raw_string_ostream Stream(ArgStr); const TemplateArgument &Arg = ArgLoc.getArgument(); Arg.print(Context->getPrintingPolicy(), Stream, /*IncludeType*/ true); Match(ArgStr, ArgLoc.getLocation()); - return ExpectedLocationVisitor:: - TraverseTemplateArgumentLoc(ArgLoc); + return ExpectedLocationVisitor::TraverseTemplateArgumentLoc(ArgLoc); } }; diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp index 9e71f9554e59517b7039aa138c7d75c4d17168fc..2feddf58cac7b23bbd53cfd27035abaa0d0d7b49 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TraversalScope.cpp @@ -12,17 +12,17 @@ using namespace clang; namespace { -class Visitor : public ExpectedLocationVisitor { +class Visitor : public ExpectedLocationVisitor { public: Visitor(ASTContext *Context) { this->Context = Context; } - bool VisitTranslationUnitDecl(TranslationUnitDecl *D) { + bool VisitTranslationUnitDecl(TranslationUnitDecl *D) override { auto &SM = D->getParentASTContext().getSourceManager(); Match("TU", SM.getLocForStartOfFile(SM.getMainFileID())); return true; } - bool VisitNamedDecl(NamedDecl *D) { + bool VisitNamedDecl(NamedDecl *D) override { if (!D->isImplicit()) Match(D->getName(), D->getLocation()); return true; diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp index 4f0cccdc274963d4df204c7de2bf9994dc4ac3c6..254d95bc20cb01899b1143db0089d53d34a33836 100644 --- a/clang/unittests/Tooling/RefactoringTest.cpp +++ b/clang/unittests/Tooling/RefactoringTest.cpp @@ -13,7 +13,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclGroup.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" @@ -647,8 +647,7 @@ TEST_F(FlushRewrittenFilesTest, StoresChangesOnDisk) { } namespace { -template -class TestVisitor : public clang::RecursiveASTVisitor { +class TestVisitor : public DynamicRecursiveASTVisitor { public: bool runOver(StringRef Code) { return runToolOnCode(std::make_unique(this), Code); @@ -698,9 +697,9 @@ void expectReplacementAt(const Replacement &Replace, EXPECT_EQ(Length, Replace.getLength()); } -class ClassDeclXVisitor : public TestVisitor { +class ClassDeclXVisitor : public TestVisitor { public: - bool VisitCXXRecordDecl(CXXRecordDecl *Record) { + bool VisitCXXRecordDecl(CXXRecordDecl *Record) override { if (Record->getName() == "X") { Replace = Replacement(*SM, Record, ""); } @@ -721,9 +720,9 @@ TEST(Replacement, ReplacesAtSpellingLocation) { expectReplacementAt(ClassDeclX.Replace, "input.cc", 17, 7); } -class CallToFVisitor : public TestVisitor { +class CallToFVisitor : public TestVisitor { public: - bool VisitCallExpr(CallExpr *Call) { + bool VisitCallExpr(CallExpr *Call) override { if (Call->getDirectCallee()->getName() == "F") { Replace = Replacement(*SM, Call, ""); } @@ -745,10 +744,9 @@ TEST(Replacement, TemplatedFunctionCall) { expectReplacementAt(CallToF.Replace, "input.cc", 43, 8); } -class NestedNameSpecifierAVisitor - : public TestVisitor { +class NestedNameSpecifierAVisitor : public TestVisitor { public: - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) override { if (NNSLoc.getNestedNameSpecifier()) { if (const NamespaceDecl* NS = NNSLoc.getNestedNameSpecifier()->getAsNamespace()) { if (NS->getName() == "a") { @@ -756,8 +754,7 @@ public: } } } - return TestVisitor::TraverseNestedNameSpecifierLoc( - NNSLoc); + return TestVisitor::TraverseNestedNameSpecifierLoc(NNSLoc); } Replacement Replace; }; diff --git a/clang/unittests/Tooling/SourceCodeTest.cpp b/clang/unittests/Tooling/SourceCodeTest.cpp index 3c24b6220a224a8ba4fd979823acdf0e18424e02..549b77752f1c21e57cf16ac87a18eb548be6f631 100644 --- a/clang/unittests/Tooling/SourceCodeTest.cpp +++ b/clang/unittests/Tooling/SourceCodeTest.cpp @@ -35,8 +35,8 @@ using tooling::validateEditRange; namespace { -struct IntLitVisitor : TestVisitor { - bool VisitIntegerLiteral(IntegerLiteral *Expr) { +struct IntLitVisitor : TestVisitor { + bool VisitIntegerLiteral(IntegerLiteral *Expr) override { OnIntLit(Expr, Context); return true; } @@ -44,8 +44,8 @@ struct IntLitVisitor : TestVisitor { std::function OnIntLit; }; -struct CallsVisitor : TestVisitor { - bool VisitCallExpr(CallExpr *Expr) { +struct CallsVisitor : TestVisitor { + bool VisitCallExpr(CallExpr *Expr) override { OnCall(Expr, Context); return true; } @@ -53,8 +53,8 @@ struct CallsVisitor : TestVisitor { std::function OnCall; }; -struct TypeLocVisitor : TestVisitor { - bool VisitTypeLoc(TypeLoc TL) { +struct TypeLocVisitor : TestVisitor { + bool VisitTypeLoc(TypeLoc TL) override { OnTypeLoc(TL, Context); return true; } @@ -97,7 +97,7 @@ static ::testing::Matcher AsRange(const SourceManager &SM, // Base class for visitors that expect a single match corresponding to a // specific annotated range. -template class AnnotatedCodeVisitor : public TestVisitor { +class AnnotatedCodeVisitor : public TestVisitor { protected: int MatchCount = 0; llvm::Annotations Code; @@ -199,9 +199,8 @@ TEST(SourceCodeTest, getExtendedText) { } TEST(SourceCodeTest, maybeExtendRange_TokenRange) { - struct ExtendTokenRangeVisitor - : AnnotatedCodeVisitor { - bool VisitCallExpr(CallExpr *CE) { + struct ExtendTokenRangeVisitor : AnnotatedCodeVisitor { + bool VisitCallExpr(CallExpr *CE) override { ++MatchCount; EXPECT_THAT(getExtendedRange(*CE, tok::TokenKind::semi, *Context), EqualsAnnotatedRange(Context, Code.range("r"))); @@ -218,8 +217,8 @@ TEST(SourceCodeTest, maybeExtendRange_TokenRange) { } TEST(SourceCodeTest, maybeExtendRange_CharRange) { - struct ExtendCharRangeVisitor : AnnotatedCodeVisitor { - bool VisitCallExpr(CallExpr *CE) { + struct ExtendCharRangeVisitor : AnnotatedCodeVisitor { + bool VisitCallExpr(CallExpr *CE) override { ++MatchCount; CharSourceRange Call = Lexer::getAsCharRange(CE->getSourceRange(), Context->getSourceManager(), @@ -238,8 +237,8 @@ TEST(SourceCodeTest, maybeExtendRange_CharRange) { } TEST(SourceCodeTest, getAssociatedRange) { - struct VarDeclsVisitor : AnnotatedCodeVisitor { - bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); } + struct VarDeclsVisitor : AnnotatedCodeVisitor { + bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); } }; VarDeclsVisitor Visitor; @@ -283,8 +282,10 @@ TEST(SourceCodeTest, getAssociatedRange) { } TEST(SourceCodeTest, getAssociatedRangeClasses) { - struct RecordDeclsVisitor : AnnotatedCodeVisitor { - bool VisitRecordDecl(RecordDecl *Decl) { return VisitDeclHelper(Decl); } + struct RecordDeclsVisitor : AnnotatedCodeVisitor { + bool VisitRecordDecl(RecordDecl *Decl) override { + return VisitDeclHelper(Decl); + } }; RecordDeclsVisitor Visitor; @@ -297,8 +298,8 @@ TEST(SourceCodeTest, getAssociatedRangeClasses) { } TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) { - struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor { - bool VisitCXXRecordDecl(CXXRecordDecl *Decl) { + struct CXXRecordDeclsVisitor : AnnotatedCodeVisitor { + bool VisitCXXRecordDecl(CXXRecordDecl *Decl) override { return Decl->getTemplateSpecializationKind() != TSK_ExplicitSpecialization || VisitDeclHelper(Decl); @@ -315,8 +316,10 @@ TEST(SourceCodeTest, getAssociatedRangeClassTemplateSpecializations) { } TEST(SourceCodeTest, getAssociatedRangeFunctions) { - struct FunctionDeclsVisitor : AnnotatedCodeVisitor { - bool VisitFunctionDecl(FunctionDecl *Decl) { return VisitDeclHelper(Decl); } + struct FunctionDeclsVisitor : AnnotatedCodeVisitor { + bool VisitFunctionDecl(FunctionDecl *Decl) override { + return VisitDeclHelper(Decl); + } }; FunctionDeclsVisitor Visitor; @@ -328,8 +331,8 @@ TEST(SourceCodeTest, getAssociatedRangeFunctions) { } TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) { - struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor { - bool VisitCXXMethodDecl(CXXMethodDecl *Decl) { + struct CXXMethodDeclsVisitor : AnnotatedCodeVisitor { + bool VisitCXXMethodDecl(CXXMethodDecl *Decl) override { // Only consider the definition of the template. return !Decl->doesThisDeclarationHaveABody() || VisitDeclHelper(Decl); } @@ -346,8 +349,8 @@ TEST(SourceCodeTest, getAssociatedRangeMemberTemplates) { } TEST(SourceCodeTest, getAssociatedRangeWithComments) { - struct VarDeclsVisitor : AnnotatedCodeVisitor { - bool VisitVarDecl(VarDecl *Decl) { return VisitDeclHelper(Decl); } + struct VarDeclsVisitor : AnnotatedCodeVisitor { + bool VisitVarDecl(VarDecl *Decl) override { return VisitDeclHelper(Decl); } }; VarDeclsVisitor Visitor; @@ -447,9 +450,9 @@ TEST(SourceCodeTest, getAssociatedRangeWithComments) { } TEST(SourceCodeTest, getAssociatedRangeInvalidForPartialExpansions) { - struct FailingVarDeclsVisitor : TestVisitor { + struct FailingVarDeclsVisitor : TestVisitor { FailingVarDeclsVisitor() {} - bool VisitVarDecl(VarDecl *Decl) { + bool VisitVarDecl(VarDecl *Decl) override { EXPECT_TRUE(getAssociatedRange(*Decl, *Context).isInvalid()); return true; } diff --git a/clang/unittests/Tooling/TestVisitor.h b/clang/unittests/Tooling/TestVisitor.h index 751ca74d1a881ca811f7dc29feb0a16a526758cb..fdf57a946a6e2d18223ce0972473210f5bf1fefa 100644 --- a/clang/unittests/Tooling/TestVisitor.h +++ b/clang/unittests/Tooling/TestVisitor.h @@ -16,7 +16,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Tooling.h" @@ -24,20 +24,11 @@ #include namespace clang { - -/// \brief Base class for simple RecursiveASTVisitor based tests. -/// -/// This is a drop-in replacement for RecursiveASTVisitor itself, with the -/// additional capability of running it over a snippet of code. -/// -/// Visits template instantiations and implicit code by default. -template -class TestVisitor : public RecursiveASTVisitor { +namespace detail { +// Use 'TestVisitor' or include 'CRTPTestVisitor.h' and use 'CRTPTestVisitor' +// instead of using this directly. +class TestVisitorHelper { public: - TestVisitor() { } - - virtual ~TestVisitor() { } - enum Language { Lang_C, Lang_CXX98, @@ -54,57 +45,63 @@ public: bool runOver(StringRef Code, Language L = Lang_CXX) { std::vector Args; switch (L) { - case Lang_C: - Args.push_back("-x"); - Args.push_back("c"); - break; - case Lang_CXX98: Args.push_back("-std=c++98"); break; - case Lang_CXX11: Args.push_back("-std=c++11"); break; - case Lang_CXX14: Args.push_back("-std=c++14"); break; - case Lang_CXX17: Args.push_back("-std=c++17"); break; - case Lang_CXX2a: Args.push_back("-std=c++2a"); break; - case Lang_OBJC: - Args.push_back("-ObjC"); - Args.push_back("-fobjc-runtime=macosx-10.12.0"); - break; - case Lang_OBJCXX11: - Args.push_back("-ObjC++"); - Args.push_back("-std=c++11"); - Args.push_back("-fblocks"); - break; + case Lang_C: + Args.push_back("-x"); + Args.push_back("c"); + break; + case Lang_CXX98: + Args.push_back("-std=c++98"); + break; + case Lang_CXX11: + Args.push_back("-std=c++11"); + break; + case Lang_CXX14: + Args.push_back("-std=c++14"); + break; + case Lang_CXX17: + Args.push_back("-std=c++17"); + break; + case Lang_CXX2a: + Args.push_back("-std=c++2a"); + break; + case Lang_OBJC: + Args.push_back("-ObjC"); + Args.push_back("-fobjc-runtime=macosx-10.12.0"); + break; + case Lang_OBJCXX11: + Args.push_back("-ObjC++"); + Args.push_back("-std=c++11"); + Args.push_back("-fblocks"); + break; } return tooling::runToolOnCodeWithArgs(CreateTestAction(), Code, Args); } - bool shouldVisitTemplateInstantiations() const { - return true; - } - - bool shouldVisitImplicitCode() const { - return true; - } - protected: + TestVisitorHelper() = default; + virtual ~TestVisitorHelper() = default; + virtual void InvokeTraverseDecl(TranslationUnitDecl *D) = 0; + virtual std::unique_ptr CreateTestAction() { return std::make_unique(this); } class FindConsumer : public ASTConsumer { public: - FindConsumer(TestVisitor *Visitor) : Visitor(Visitor) {} + FindConsumer(TestVisitorHelper *Visitor) : Visitor(Visitor) {} void HandleTranslationUnit(clang::ASTContext &Context) override { Visitor->Context = &Context; - Visitor->TraverseDecl(Context.getTranslationUnitDecl()); + Visitor->InvokeTraverseDecl(Context.getTranslationUnitDecl()); } private: - TestVisitor *Visitor; + TestVisitorHelper *Visitor; }; class TestAction : public ASTFrontendAction { public: - TestAction(TestVisitor *Visitor) : Visitor(Visitor) {} + TestAction(TestVisitorHelper *Visitor) : Visitor(Visitor) {} std::unique_ptr CreateASTConsumer(CompilerInstance &, llvm::StringRef dummy) override { @@ -113,20 +110,13 @@ protected: } protected: - TestVisitor *Visitor; + TestVisitorHelper *Visitor; }; ASTContext *Context; }; -/// \brief A RecursiveASTVisitor to check that certain matches are (or are -/// not) observed during visitation. -/// -/// This is a RecursiveASTVisitor for testing the RecursiveASTVisitor itself, -/// and allows simple creation of test visitors running matches on only a small -/// subset of the Visit* methods. -template class Visitor = TestVisitor> -class ExpectedLocationVisitor : public Visitor { +class ExpectedLocationVisitorHelper { public: /// \brief Expect 'Match' *not* to occur at the given 'Line' and 'Column'. /// @@ -147,37 +137,44 @@ public: } /// \brief Checks that all expected matches have been found. - ~ExpectedLocationVisitor() override { - for (typename std::vector::const_iterator - It = ExpectedMatches.begin(), End = ExpectedMatches.end(); + virtual ~ExpectedLocationVisitorHelper() { + // FIXME: Range-based for loop. + for (std::vector::const_iterator + It = ExpectedMatches.begin(), + End = ExpectedMatches.end(); It != End; ++It) { It->ExpectFound(); } } protected: + virtual ASTContext *getASTContext() = 0; + /// \brief Checks an actual match against expected and disallowed matches. /// /// Implementations are required to call this with appropriate values /// for 'Name' during visitation. void Match(StringRef Name, SourceLocation Location) { - const FullSourceLoc FullLocation = this->Context->getFullLoc(Location); + const FullSourceLoc FullLocation = getASTContext()->getFullLoc(Location); - for (typename std::vector::const_iterator - It = DisallowedMatches.begin(), End = DisallowedMatches.end(); + // FIXME: Range-based for loop. + for (std::vector::const_iterator + It = DisallowedMatches.begin(), + End = DisallowedMatches.end(); It != End; ++It) { EXPECT_FALSE(It->Matches(Name, FullLocation)) << "Matched disallowed " << *It; } - for (typename std::vector::iterator - It = ExpectedMatches.begin(), End = ExpectedMatches.end(); + // FIXME: Range-based for loop. + for (std::vector::iterator It = ExpectedMatches.begin(), + End = ExpectedMatches.end(); It != End; ++It) { - It->UpdateFor(Name, FullLocation, this->Context->getSourceManager()); + It->UpdateFor(Name, FullLocation, getASTContext()->getSourceManager()); } } - private: +private: struct MatchCandidate { std::string ExpectedName; unsigned LineNumber; @@ -247,6 +244,41 @@ protected: std::vector DisallowedMatches; std::vector ExpectedMatches; }; -} +} // namespace detail + +/// \brief Base class for simple (Dynamic)RecursiveASTVisitor based tests. +/// +/// This is a drop-in replacement for DynamicRecursiveASTVisitor itself, with +/// the additional capability of running it over a snippet of code. +/// +/// Visits template instantiations and implicit code by default. +/// +/// For post-order traversal etc. use CTRPTestVisitor from +/// CTRPTestVisitor.h instead. +class TestVisitor : public DynamicRecursiveASTVisitor, + public detail::TestVisitorHelper { +public: + TestVisitor() { + ShouldVisitTemplateInstantiations = true; + ShouldVisitImplicitCode = true; + } + + void InvokeTraverseDecl(TranslationUnitDecl *D) override { TraverseDecl(D); } +}; + +/// \brief A RecursiveASTVisitor to check that certain matches are (or are +/// not) observed during visitation. +/// +/// This is a RecursiveASTVisitor for testing the RecursiveASTVisitor itself, +/// and allows simple creation of test visitors running matches on only a small +/// subset of the Visit* methods. +/// +/// For post-order traversal etc. use CTRPExpectedLocationVisitor from +/// CTRPTestVisitor.h instead. +class ExpectedLocationVisitor : public TestVisitor, + public detail::ExpectedLocationVisitorHelper { + ASTContext *getASTContext() override { return Context; } +}; +} // namespace clang #endif diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index f41a44fa0922a1de1deb42565acfa59e245da29b..0b65577a05193f03f927a3d01628601405dda46f 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -384,7 +384,8 @@ struct CommandLineExtractorTest : public ::testing::Test { public: CommandLineExtractorTest() : InMemoryFS(new llvm::vfs::InMemoryFileSystem), - Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)), + Diags(CompilerInstance::createDiagnostics(*InMemoryFS, + new DiagnosticOptions)), Driver("clang", llvm::sys::getDefaultTargetTriple(), *Diags, "clang LLVM compiler", overlayRealFS(InMemoryFS)) {} diff --git a/clang/utils/TableGen/ASTTableGen.cpp b/clang/utils/TableGen/ASTTableGen.cpp index 46bb6c21997f097e7be33a51465a5140a7b5c49e..6fa744fb547e2dc96aa57f5862f30c5b6e43ddd2 100644 --- a/clang/utils/TableGen/ASTTableGen.cpp +++ b/clang/utils/TableGen/ASTTableGen.cpp @@ -1,4 +1,4 @@ -//=== ASTTableGen.cpp - Helper functions for working with AST records -----===// +//===-- ASTTableGen.cpp - Helper functions for working with AST records ---===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -13,9 +13,8 @@ //===----------------------------------------------------------------------===// #include "ASTTableGen.h" -#include "llvm/TableGen/Record.h" #include "llvm/TableGen/Error.h" -#include +#include "llvm/TableGen/Record.h" using namespace llvm; using namespace clang; diff --git a/clang/utils/TableGen/ClangASTNodesEmitter.cpp b/clang/utils/TableGen/ClangASTNodesEmitter.cpp index 9421f48d5487ca349643ebba6a95105db26a60b3..16749d118362463cbbf119be8b1525d30ca477d4 100644 --- a/clang/utils/TableGen/ClangASTNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTNodesEmitter.cpp @@ -1,4 +1,4 @@ -//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===// +//===-- ClangASTNodesEmitter.cpp - Generate Clang AST node tables ---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp index 3151ff199f57625d42bcbe10c9043a513f571230..acff6febeb8cfab72fcd7309926463b058b83dcc 100644 --- a/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp +++ b/clang/utils/TableGen/ClangASTPropertiesEmitter.cpp @@ -1,4 +1,4 @@ -//=== ClangASTPropsEmitter.cpp - Generate Clang AST properties --*- C++ -*-===// +//===-- ClangASTPropsEmitter.cpp - Generate Clang AST properties ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -13,14 +13,12 @@ #include "ASTTableGen.h" #include "TableGenBackends.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include #include -#include #include #include using namespace llvm; diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index b450989aeeddca97e12e6826dd4e24ba6faf2093..4aa7594ffa6eb7c271b6e4b43e89da318a2c57f2 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1,4 +1,4 @@ -//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=// +//===-- ClangAttrEmitter.cpp - Generate Clang attribute handling ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -20,18 +20,14 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/StringMatcher.h" #include "llvm/TableGen/TableGenBackend.h" -#include #include #include #include @@ -40,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp index 57a1fc06b26b1664712b725fbbce92083d84921c..6c3604adc92b994f4b30fe59ce29dd9f5534a180 100644 --- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp +++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp @@ -1,4 +1,4 @@ -//=- ClangBuiltinsEmitter.cpp - Generate Clang builtins tables -*- C++ -*-====// +//===-- ClangBuiltinsEmitter.cpp - Generate Clang builtins tables ---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp b/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp index 45a97425ef920aa2d8482ebd1a0f24b9a68a1636..f15e30cd3f8f4024a39e56dd58fe39836a353702 100644 --- a/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp +++ b/clang/utils/TableGen/ClangCommentCommandInfoEmitter.cpp @@ -1,4 +1,4 @@ -//===--- ClangCommentCommandInfoEmitter.cpp - Generate command lists -----====// +//===-- ClangCommentCommandInfoEmitter.cpp - Generate command lists -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp b/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp index 2d615760814e01b25ee19bf18881f90be9b8f34a..b8d8ac853a5c03823a8f337a5ae4157f648ebcca 100644 --- a/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp +++ b/clang/utils/TableGen/ClangCommentHTMLNamedCharacterReferenceEmitter.cpp @@ -1,4 +1,4 @@ -//===--- ClangCommentHTMLNamedCharacterReferenceEmitter.cpp -----------------=// +//===-- ClangCommentHTMLNamedCharacterReferenceEmitter.cpp ----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp b/clang/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp index 7d65cfe0d3f5292c5754eaf919dc1eb945a6d52f..c47553cc81a9cb30730aab487a19133229cc885b 100644 --- a/clang/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp +++ b/clang/utils/TableGen/ClangCommentHTMLTagsEmitter.cpp @@ -1,4 +1,4 @@ -//===--- ClangCommentHTMLTagsEmitter.cpp - Generate HTML tag list for Clang -=// +//===-- ClangCommentHTMLTagsEmitter.cpp - Generate HTML tag list ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp b/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp index dae6710d752358d043eee6ef1e51a6bc2fa585c5..50e90691c555bf95def0b5062834ec2af82db6d8 100644 --- a/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp +++ b/clang/utils/TableGen/ClangDataCollectorsEmitter.cpp @@ -1,3 +1,15 @@ +//===-- ClangDataCollectorsEmitter.cpp - Generate Clang data collector ----===// +// +// 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 tablegen backend emit Clang data collector tables. +// +//===----------------------------------------------------------------------===// + #include "TableGenBackends.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index 34e2e8f47ae71a0f949a55ba0506fa7688fe20c8..6a4a64a0813063ce21ef16f3b044b12e329bc660 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -1,4 +1,4 @@ -//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*- +//===-- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables ---===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,7 +14,6 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -44,35 +43,28 @@ class DiagGroupParentMap { public: DiagGroupParentMap(const RecordKeeper &records) : Records(records) { - ArrayRef DiagGroups = - Records.getAllDerivedDefinitions("DiagGroup"); - for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { - std::vector SubGroups = - DiagGroups[i]->getValueAsListOfDefs("SubGroups"); - for (unsigned j = 0, e = SubGroups.size(); j != e; ++j) - Mapping[SubGroups[j]].push_back(DiagGroups[i]); - } + for (const Record *Group : Records.getAllDerivedDefinitions("DiagGroup")) + for (const Record *SubGroup : Group->getValueAsListOfDefs("SubGroups")) + Mapping[SubGroup].push_back(Group); } - const std::vector &getParents(const Record *Group) { + ArrayRef getParents(const Record *Group) { return Mapping[Group]; } }; } // end anonymous namespace. -static std::string +static StringRef getCategoryFromDiagGroup(const Record *Group, DiagGroupParentMap &DiagGroupParents) { // If the DiagGroup has a category, return it. - std::string CatName = std::string(Group->getValueAsString("CategoryName")); + StringRef CatName = Group->getValueAsString("CategoryName"); if (!CatName.empty()) return CatName; // The diag group may the subgroup of one or more other diagnostic groups, // check these for a category as well. - const std::vector &Parents = - DiagGroupParents.getParents(Group); - for (unsigned i = 0, e = Parents.size(); i != e; ++i) { - CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents); + for (const Record *Parent : DiagGroupParents.getParents(Group)) { + CatName = getCategoryFromDiagGroup(Parent, DiagGroupParents); if (!CatName.empty()) return CatName; } return ""; @@ -80,25 +72,26 @@ getCategoryFromDiagGroup(const Record *Group, /// getDiagnosticCategory - Return the category that the specified diagnostic /// lives in. -static std::string getDiagnosticCategory(const Record *R, - DiagGroupParentMap &DiagGroupParents) { +static StringRef getDiagnosticCategory(const Record *R, + DiagGroupParentMap &DiagGroupParents) { // If the diagnostic is in a group, and that group has a category, use it. if (const auto *Group = dyn_cast(R->getValueInit("Group"))) { // Check the diagnostic's diag group for a category. - std::string CatName = getCategoryFromDiagGroup(Group->getDef(), - DiagGroupParents); + StringRef CatName = + getCategoryFromDiagGroup(Group->getDef(), DiagGroupParents); if (!CatName.empty()) return CatName; } // If the diagnostic itself has a category, get it. - return std::string(R->getValueAsString("CategoryName")); + return R->getValueAsString("CategoryName"); } namespace { class DiagCategoryIDMap { const RecordKeeper &Records; StringMap CategoryIDs; - std::vector CategoryStrings; + std::vector CategoryStrings; + public: DiagCategoryIDMap(const RecordKeeper &records) : Records(records) { DiagGroupParentMap ParentInfo(Records); @@ -107,10 +100,9 @@ namespace { CategoryStrings.push_back(""); CategoryIDs[""] = 0; - ArrayRef Diags = - Records.getAllDerivedDefinitions("Diagnostic"); - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - std::string Category = getDiagnosticCategory(Diags[i], ParentInfo); + for (const Record *Diag : + Records.getAllDerivedDefinitions("Diagnostic")) { + StringRef Category = getDiagnosticCategory(Diag, ParentInfo); if (Category.empty()) continue; // Skip diags with no category. unsigned &ID = CategoryIDs[Category]; @@ -125,7 +117,7 @@ namespace { return CategoryIDs[CategoryString]; } - typedef std::vector::const_iterator const_iterator; + typedef std::vector::const_iterator const_iterator; const_iterator begin() const { return CategoryStrings.begin(); } const_iterator end() const { return CategoryStrings.end(); } }; @@ -133,7 +125,7 @@ namespace { struct GroupInfo { StringRef GroupName; std::vector DiagsInGroup; - std::vector SubGroups; + std::vector SubGroups; unsigned IDNo = 0; SmallVector Defs; @@ -153,42 +145,37 @@ static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) { RHS->getValueAsString("GroupName"); } +using DiagsInGroupTy = std::map; + /// Invert the 1-[0/1] mapping of diags to group into a one to many /// mapping of groups to diags in the group. static void groupDiagnostics(ArrayRef Diags, ArrayRef DiagGroups, - std::map &DiagsInGroup) { - - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - const Record *R = Diags[i]; + DiagsInGroupTy &DiagsInGroup) { + for (const Record *R : Diags) { const auto *DI = dyn_cast(R->getValueInit("Group")); if (!DI) continue; assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" && "Note can't be in a DiagGroup"); - std::string GroupName = - std::string(DI->getDef()->getValueAsString("GroupName")); + StringRef GroupName = DI->getDef()->getValueAsString("GroupName"); DiagsInGroup[GroupName].DiagsInGroup.push_back(R); } // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty // groups (these are warnings that GCC supports that clang never produces). - for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { - const Record *Group = DiagGroups[i]; - GroupInfo &GI = - DiagsInGroup[std::string(Group->getValueAsString("GroupName"))]; + for (const Record *Group : DiagGroups) { + GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; GI.GroupName = Group->getName(); GI.Defs.push_back(Group); for (const Record *SubGroup : Group->getValueAsListOfDefs("SubGroups")) - GI.SubGroups.push_back(SubGroup->getValueAsString("GroupName").str()); + GI.SubGroups.push_back(SubGroup->getValueAsString("GroupName")); } // Assign unique ID numbers to the groups. - unsigned IDNo = 0; - for (std::map::iterator - I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo) - I->second.IDNo = IDNo; + for (auto [IdNo, Iter] : enumerate(DiagsInGroup)) + Iter.second.IDNo = IdNo; // Warn if the same group is defined more than once (including implicitly). for (auto &Group : DiagsInGroup) { @@ -256,14 +243,14 @@ class InferPedantic { DiagGroupParentMap &DiagGroupParents; ArrayRef Diags; const std::vector DiagGroups; - std::map &DiagsInGroup; + DiagsInGroupTy &DiagsInGroup; DenseSet DiagsSet; GMap GroupCount; public: InferPedantic(DiagGroupParentMap &DiagGroupParents, ArrayRef Diags, ArrayRef DiagGroups, - std::map &DiagsInGroup) + DiagsInGroupTy &DiagsInGroup) : DiagGroupParents(DiagGroupParents), Diags(Diags), DiagGroups(DiagGroups), DiagsInGroup(DiagsInGroup) {} @@ -292,15 +279,12 @@ private: } // end anonymous namespace bool InferPedantic::isSubGroupOfGroup(const Record *Group, StringRef GName) { - const std::string &GroupName = - std::string(Group->getValueAsString("GroupName")); + StringRef GroupName = Group->getValueAsString("GroupName"); if (GName == GroupName) return true; - const std::vector &Parents = - DiagGroupParents.getParents(Group); - for (unsigned i = 0, e = Parents.size(); i != e; ++i) - if (isSubGroupOfGroup(Parents[i], GName)) + for (const Record *Parent : DiagGroupParents.getParents(Group)) + if (isSubGroupOfGroup(Parent, GName)) return true; return false; @@ -308,23 +292,19 @@ bool InferPedantic::isSubGroupOfGroup(const Record *Group, StringRef GName) { /// Determine if the diagnostic is an extension. bool InferPedantic::isExtension(const Record *Diag) { - const std::string &ClsName = - std::string(Diag->getValueAsDef("Class")->getName()); - return ClsName == "CLASS_EXTENSION"; + return Diag->getValueAsDef("Class")->getName() == "CLASS_EXTENSION"; } bool InferPedantic::isOffByDefault(const Record *Diag) { - const std::string &DefSeverity = std::string( - Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name")); - return DefSeverity == "Ignored"; + return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name") == + "Ignored"; } bool InferPedantic::groupInPedantic(const Record *Group, bool increment) { GMap::mapped_type &V = GroupCount[Group]; // Lazily compute the threshold value for the group count. if (!V.second) { - const GroupInfo &GI = - DiagsInGroup[std::string(Group->getValueAsString("GroupName"))]; + const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")]; V.second = GI.SubGroups.size() + GI.DiagsInGroup.size(); } @@ -342,12 +322,9 @@ void InferPedantic::markGroup(const Record *Group) { // covered by -Wpedantic, increment the count of parent groups. Once the // group's count is equal to the number of subgroups and diagnostics in // that group, we can safely add this group to -Wpedantic. - if (groupInPedantic(Group, /* increment */ true)) { - const std::vector &Parents = - DiagGroupParents.getParents(Group); - for (unsigned i = 0, e = Parents.size(); i != e; ++i) - markGroup(Parents[i]); - } + if (groupInPedantic(Group, /* increment */ true)) + for (const Record *Parent : DiagGroupParents.getParents(Group)) + markGroup(Parent); } void InferPedantic::compute(VecOrSet DiagsInPedantic, @@ -355,15 +332,14 @@ void InferPedantic::compute(VecOrSet DiagsInPedantic, // All extensions that are not on by default are implicitly in the // "pedantic" group. For those that aren't explicitly included in -Wpedantic, // mark them for consideration to be included in -Wpedantic directly. - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - const Record *R = Diags[i]; - if (isExtension(R) && isOffByDefault(R)) { - DiagsSet.insert(R); - if (const auto *Group = dyn_cast(R->getValueInit("Group"))) { - const Record *GroupRec = Group->getDef(); - if (!isSubGroupOfGroup(GroupRec, "pedantic")) { - markGroup(GroupRec); - } + for (const Record *R : Diags) { + if (!isExtension(R) || !isOffByDefault(R)) + continue; + DiagsSet.insert(R); + if (const auto *Group = dyn_cast(R->getValueInit("Group"))) { + const Record *GroupRec = Group->getDef(); + if (!isSubGroupOfGroup(GroupRec, "pedantic")) { + markGroup(GroupRec); } } } @@ -371,8 +347,7 @@ void InferPedantic::compute(VecOrSet DiagsInPedantic, // Compute the set of diagnostics that are directly in -Wpedantic. We // march through Diags a second time to ensure the results are emitted // in deterministic order. - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - const Record *R = Diags[i]; + for (const Record *R : Diags) { if (!DiagsSet.count(R)) continue; // Check if the group is implicitly in -Wpedantic. If so, @@ -386,9 +361,8 @@ void InferPedantic::compute(VecOrSet DiagsInPedantic, // -Wpedantic. Include it in -Wpedantic directly. if (auto *V = DiagsInPedantic.dyn_cast()) V->push_back(R); - else { - DiagsInPedantic.get()->insert(R); - } + else + DiagsInPedantic.get()->insert(R); } if (!GroupsInPedantic) @@ -397,8 +371,7 @@ void InferPedantic::compute(VecOrSet DiagsInPedantic, // Compute the set of groups that are directly in -Wpedantic. We // march through the groups to ensure the results are emitted /// in a deterministc order. - for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) { - const Record *Group = DiagGroups[i]; + for (const Record *Group : DiagGroups) { if (!groupInPedantic(Group)) continue; @@ -415,9 +388,8 @@ void InferPedantic::compute(VecOrSet DiagsInPedantic, if (auto *V = GroupsInPedantic.dyn_cast()) V->push_back(Group); - else { - GroupsInPedantic.get()->insert(Group); - } + else + GroupsInPedantic.get()->insert(Group); } } @@ -440,6 +412,7 @@ enum ModifierType { MT_Plural, MT_Diff, MT_Ordinal, + MT_Human, MT_S, MT_Q, MT_ObjCClass, @@ -458,6 +431,8 @@ static StringRef getModifierName(ModifierType MT) { return "plural"; case MT_Ordinal: return "ordinal"; + case MT_Human: + return "human"; case MT_S: return "s"; case MT_Q: @@ -970,10 +945,11 @@ public: void VisitPlural(PluralPiece *P) { Result += "%plural{"; assert(P->Options.size() == P->OptionPrefixes.size()); - for (unsigned I = 0, End = P->Options.size(); I < End; ++I) { - if (P->OptionPrefixes[I]) - Visit(P->OptionPrefixes[I]); - Visit(P->Options[I]); + for (const auto [Prefix, Option] : + zip_equal(P->OptionPrefixes, P->Options)) { + if (Prefix) + Visit(Prefix); + Visit(Option); Result += "|"; } if (!P->Options.empty()) @@ -1053,6 +1029,7 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text, .Case("plural", MT_Plural) .Case("s", MT_S) .Case("ordinal", MT_Ordinal) + .Case("human", MT_Human) .Case("q", MT_Q) .Case("objcclass", MT_ObjCClass) .Case("objcinstance", MT_ObjCInstance) @@ -1154,7 +1131,8 @@ Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text, case MT_Placeholder: case MT_ObjCClass: case MT_ObjCInstance: - case MT_Ordinal: { + case MT_Ordinal: + case MT_Human: { Parsed.push_back(New(ModType, parseModifier(Text))); continue; } @@ -1201,15 +1179,11 @@ std::string DiagnosticTextBuilder::buildForDefinition(const Record *R) { //===----------------------------------------------------------------------===// static bool isError(const Record &Diag) { - const std::string &ClsName = - std::string(Diag.getValueAsDef("Class")->getName()); - return ClsName == "CLASS_ERROR"; + return Diag.getValueAsDef("Class")->getName() == "CLASS_ERROR"; } static bool isRemark(const Record &Diag) { - const std::string &ClsName = - std::string(Diag.getValueAsDef("Class")->getName()); - return ClsName == "CLASS_REMARK"; + return Diag.getValueAsDef("Class")->getName() == "CLASS_REMARK"; } // Presumes the text has been split at the first whitespace or hyphen. @@ -1426,7 +1400,7 @@ void clang::EmitClangDiagsDefs(const RecordKeeper &Records, raw_ostream &OS, ArrayRef DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); - std::map DiagsInGroup; + DiagsInGroupTy DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); DiagCategoryIDMap CategoryIDs(Records); @@ -1437,16 +1411,13 @@ void clang::EmitClangDiagsDefs(const RecordKeeper &Records, raw_ostream &OS, InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr); - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - const Record &R = *Diags[i]; - + for (const Record &R : make_pointee_range(Diags)) { // Check if this is an error that is accidentally in a warning // group. if (isError(R)) { if (const auto *Group = dyn_cast(R.getValueInit("Group"))) { const Record *GroupRec = Group->getDef(); - const std::string &GroupName = - std::string(GroupRec->getValueAsString("GroupName")); + StringRef GroupName = GroupRec->getValueAsString("GroupName"); PrintFatalError(R.getLoc(), "Error " + R.getName() + " cannot be in a warning group [" + GroupName + "]"); } @@ -1479,13 +1450,11 @@ void clang::EmitClangDiagsDefs(const RecordKeeper &Records, raw_ostream &OS, // Warning group associated with the diagnostic. This is stored as an index // into the alphabetically sorted warning group table. if (const auto *DI = dyn_cast(R.getValueInit("Group"))) { - std::map::iterator I = DiagsInGroup.find( - std::string(DI->getDef()->getValueAsString("GroupName"))); + auto I = DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName")); assert(I != DiagsInGroup.end()); OS << ", " << I->second.IDNo; } else if (DiagsInPedantic.count(&R)) { - std::map::iterator I = - DiagsInGroup.find("pedantic"); + auto I = DiagsInGroup.find("pedantic"); assert(I != DiagsInGroup.end() && "pedantic group not defined"); OS << ", " << I->second.IDNo; } else { @@ -1549,29 +1518,25 @@ static std::string getDiagCategoryEnum(StringRef name) { /// } /// \endcode /// -static void emitDiagSubGroups(std::map &DiagsInGroup, +static void emitDiagSubGroups(DiagsInGroupTy &DiagsInGroup, RecordVec &GroupsInPedantic, raw_ostream &OS) { OS << "static const int16_t DiagSubGroups[] = {\n" << " /* Empty */ -1,\n"; - for (auto const &I : DiagsInGroup) { - const bool IsPedantic = I.first == "pedantic"; - - const std::vector &SubGroups = I.second.SubGroups; + for (auto const &[Name, Group] : DiagsInGroup) { + const bool IsPedantic = Name == "pedantic"; + const std::vector &SubGroups = Group.SubGroups; if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) { - OS << " /* DiagSubGroup" << I.second.IDNo << " */ "; - for (auto const &SubGroup : SubGroups) { - std::map::const_iterator RI = - DiagsInGroup.find(SubGroup); + OS << " /* DiagSubGroup" << Group.IDNo << " */ "; + for (StringRef SubGroup : SubGroups) { + auto RI = DiagsInGroup.find(SubGroup); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } // Emit the groups implicitly in "pedantic". if (IsPedantic) { for (auto const &Group : GroupsInPedantic) { - const std::string &GroupName = - std::string(Group->getValueAsString("GroupName")); - std::map::const_iterator RI = - DiagsInGroup.find(GroupName); + StringRef GroupName = Group->getValueAsString("GroupName"); + auto RI = DiagsInGroup.find(GroupName); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } @@ -1601,16 +1566,16 @@ static void emitDiagSubGroups(std::map &DiagsInGroup, /// }; /// \endcode /// -static void emitDiagArrays(std::map &DiagsInGroup, +static void emitDiagArrays(DiagsInGroupTy &DiagsInGroup, RecordVec &DiagsInPedantic, raw_ostream &OS) { OS << "static const int16_t DiagArrays[] = {\n" << " /* Empty */ -1,\n"; - for (auto const &I : DiagsInGroup) { - const bool IsPedantic = I.first == "pedantic"; + for (const auto &[Name, Group] : DiagsInGroup) { + const bool IsPedantic = Name == "pedantic"; - const std::vector &V = I.second.DiagsInGroup; + const std::vector &V = Group.DiagsInGroup; if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) { - OS << " /* DiagArray" << I.second.IDNo << " */ "; + OS << " /* DiagArray" << Group.IDNo << " */ "; for (auto *Record : V) OS << "diag::" << Record->getName() << ", "; // Emit the diagnostics implicitly in "pedantic". @@ -1653,7 +1618,7 @@ static void emitDiagGroupNames(const StringToOffsetTable &GroupNames, /// static const char DiagGroupNames[]; /// #endif /// \endcode -static void emitAllDiagArrays(std::map &DiagsInGroup, +static void emitAllDiagArrays(DiagsInGroupTy &DiagsInGroup, RecordVec &DiagsInPedantic, RecordVec &GroupsInPedantic, const StringToOffsetTable &GroupNames, @@ -1680,7 +1645,7 @@ static void emitAllDiagArrays(std::map &DiagsInGroup, /// {/* deprecated */ 1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */ 9}, /// #endif /// \endcode -static void emitDiagTable(std::map &DiagsInGroup, +static void emitDiagTable(DiagsInGroupTy &DiagsInGroup, RecordVec &DiagsInPedantic, RecordVec &GroupsInPedantic, const StringToOffsetTable &GroupNames, @@ -1692,31 +1657,29 @@ static void emitDiagTable(std::map &DiagsInGroup, OS << "\n#ifdef DIAG_ENTRY\n"; unsigned SubGroupIndex = 1, DiagArrayIndex = 1; - for (auto const &I: DiagsInGroup) { + for (auto const &[Name, GroupInfo] : DiagsInGroup) { // Group option string. OS << "DIAG_ENTRY("; - OS << I.second.GroupName << " /* "; - - if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789!@#$%^*-+=:?") != - std::string::npos) - PrintFatalError("Invalid character in diagnostic group '" + I.first + - "'"); - OS << I.first << " */, "; + OS << GroupInfo.GroupName << " /* "; + + if (Name.find_first_not_of("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789!@#$%^*-+=:?") != std::string::npos) + PrintFatalError("Invalid character in diagnostic group '" + Name + "'"); + OS << Name << " */, "; // Store a pascal-style length byte at the beginning of the string. - std::string Name = char(I.first.size()) + I.first; - OS << *GroupNames.GetStringOffset(Name) << ", "; + std::string PascalName = char(Name.size()) + Name.str(); + OS << *GroupNames.GetStringOffset(PascalName) << ", "; // Special handling for 'pedantic'. - const bool IsPedantic = I.first == "pedantic"; + const bool IsPedantic = Name == "pedantic"; // Diagnostics in the group. - const std::vector &V = I.second.DiagsInGroup; + const std::vector &V = GroupInfo.DiagsInGroup; const bool hasDiags = !V.empty() || (IsPedantic && !DiagsInPedantic.empty()); if (hasDiags) { - OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex + OS << "/* DiagArray" << GroupInfo.IDNo << " */ " << DiagArrayIndex << ", "; if (IsPedantic) DiagArrayIndex += DiagsInPedantic.size(); @@ -1726,11 +1689,11 @@ static void emitDiagTable(std::map &DiagsInGroup, } // Subgroups. - const std::vector &SubGroups = I.second.SubGroups; + const std::vector &SubGroups = GroupInfo.SubGroups; const bool hasSubGroups = !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty()); if (hasSubGroups) { - OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex + OS << "/* DiagSubGroup" << GroupInfo.IDNo << " */ " << SubGroupIndex << ", "; if (IsPedantic) SubGroupIndex += GroupsInPedantic.size(); @@ -1739,7 +1702,7 @@ static void emitDiagTable(std::map &DiagsInGroup, OS << "0, "; } - std::string Documentation = I.second.Defs.back() + std::string Documentation = GroupInfo.Defs.back() ->getValue("Documentation") ->getValue() ->getAsUnquotedString(); @@ -1782,7 +1745,7 @@ void clang::EmitClangDiagGroups(const RecordKeeper &Records, raw_ostream &OS) { ArrayRef DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); - std::map DiagsInGroup; + DiagsInGroupTy DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); // All extensions are implicitly in the "pedantic" group. Record the @@ -1794,13 +1757,10 @@ void clang::EmitClangDiagGroups(const RecordKeeper &Records, raw_ostream &OS) { inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic); StringToOffsetTable GroupNames; - for (std::map::const_iterator - I = DiagsInGroup.begin(), - E = DiagsInGroup.end(); - I != E; ++I) { + for (const auto &[Name, Group] : DiagsInGroup) { // Store a pascal-style length byte at the beginning of the string. - std::string Name = char(I->first.size()) + I->first; - GroupNames.GetOrAddStringOffset(Name, false); + std::string PascalName = char(Name.size()) + Name.str(); + GroupNames.GetOrAddStringOffset(PascalName, false); } emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames, @@ -1814,38 +1774,17 @@ void clang::EmitClangDiagGroups(const RecordKeeper &Records, raw_ostream &OS) { // Diagnostic name index generation //===----------------------------------------------------------------------===// -namespace { -struct RecordIndexElement -{ - RecordIndexElement() {} - explicit RecordIndexElement(Record const &R) - : Name(std::string(R.getName())) {} - - std::string Name; -}; -} // end anonymous namespace. - void clang::EmitClangDiagsIndexName(const RecordKeeper &Records, raw_ostream &OS) { - ArrayRef Diags = + std::vector Diags = Records.getAllDerivedDefinitions("Diagnostic"); - std::vector Index; - Index.reserve(Diags.size()); - for (unsigned i = 0, e = Diags.size(); i != e; ++i) { - const Record &R = *(Diags[i]); - Index.push_back(RecordIndexElement(R)); - } - - sort(Index, [](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) { - return Lhs.Name < Rhs.Name; + sort(Diags, [](const Record *LHS, const Record *RHS) { + return LHS->getName() < RHS->getName(); }); - for (unsigned i = 0, e = Index.size(); i != e; ++i) { - const RecordIndexElement &R = Index[i]; - - OS << "DIAG_NAME_INDEX(" << R.Name << ")\n"; - } + for (const Record *Elem : Diags) + OS << "DIAG_NAME_INDEX(" << Elem->getName() << ")\n"; } //===----------------------------------------------------------------------===// @@ -1856,14 +1795,14 @@ namespace docs { namespace { bool isRemarkGroup(const Record *DiagGroup, - const std::map &DiagsInGroup) { + const DiagsInGroupTy &DiagsInGroup) { bool AnyRemarks = false, AnyNonRemarks = false; std::function Visit = [&](StringRef GroupName) { - auto &GroupInfo = DiagsInGroup.find(std::string(GroupName))->second; + auto &GroupInfo = DiagsInGroup.find(GroupName)->second; for (const Record *Diag : GroupInfo.DiagsInGroup) (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true; - for (const auto &Name : GroupInfo.SubGroups) + for (StringRef Name : GroupInfo.SubGroups) Visit(Name); }; Visit(DiagGroup->getValueAsString("GroupName")); @@ -1880,13 +1819,12 @@ std::string getDefaultSeverity(const Record *Diag) { Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name")); } -std::set -getDefaultSeverities(const Record *DiagGroup, - const std::map &DiagsInGroup) { +std::set getDefaultSeverities(const Record *DiagGroup, + const DiagsInGroupTy &DiagsInGroup) { std::set States; std::function Visit = [&](StringRef GroupName) { - auto &GroupInfo = DiagsInGroup.find(std::string(GroupName))->second; + auto &GroupInfo = DiagsInGroup.find(GroupName)->second; for (const Record *Diag : GroupInfo.DiagsInGroup) States.insert(getDefaultSeverity(Diag)); for (const auto &Name : GroupInfo.SubGroups) @@ -1940,7 +1878,7 @@ void clang::EmitClangDiagDocs(const RecordKeeper &Records, raw_ostream &OS) { DiagGroupParentMap DGParentMap(Records); - std::map DiagsInGroup; + DiagsInGroupTy DiagsInGroup; groupDiagnostics(Diags, DiagGroups, DiagsInGroup); // Compute the set of diagnostics that are in -Wpedantic. @@ -1961,8 +1899,7 @@ void clang::EmitClangDiagDocs(const RecordKeeper &Records, raw_ostream &OS) { DiagsInPedantic.begin(), DiagsInPedantic.end()); for (auto *Group : GroupsInPedantic) - PedDiags.SubGroups.push_back( - std::string(Group->getValueAsString("GroupName"))); + PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName")); } // FIXME: Write diagnostic categories and link to diagnostic groups in each. @@ -2008,7 +1945,7 @@ void clang::EmitClangDiagDocs(const RecordKeeper &Records, raw_ostream &OS) { bool First = true; sort(GroupInfo.SubGroups); - for (const auto &Name : GroupInfo.SubGroups) { + for (StringRef Name : GroupInfo.SubGroups) { if (!First) OS << ", "; OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_"; First = false; diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp b/clang/utils/TableGen/ClangOpcodesEmitter.cpp index a18220fe23c41781b01e9dc326873bb85f70199b..d6ab307dd80bcffefcbb8c15c8edf846a337540e 100644 --- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp +++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp @@ -1,4 +1,4 @@ -//=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ -*-===// +//===-- ClangOpcodesEmitter.cpp - constexpr interpreter opcodes -----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp index 386a965445ce864ca0c7705a2be0c6336a965158..f78b09a755591b6db6bfcf17213c7ca1926e319a 100644 --- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -1,4 +1,4 @@ -//===- ClangOpenCLBuiltinEmitter.cpp - Generate Clang OpenCL Builtin handling +//===-- ClangOpenCLBuiltinEmitter.cpp - Generate OpenCL Builtin handling --===// // // The LLVM Compiler Infrastructure // @@ -18,7 +18,6 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" diff --git a/clang/utils/TableGen/ClangOptionDocEmitter.cpp b/clang/utils/TableGen/ClangOptionDocEmitter.cpp index ba8840c1bdca78cc22331446ad90bcc6049e88f7..e08fb11df310023930cf39840834fa2883666352 100644 --- a/clang/utils/TableGen/ClangOptionDocEmitter.cpp +++ b/clang/utils/TableGen/ClangOptionDocEmitter.cpp @@ -1,4 +1,4 @@ -//===- ClangOptionDocEmitter.cpp - Documentation for command line flags ---===// +//===-- ClangOptionDocEmitter.cpp - Documentation for command line flags --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,11 +9,10 @@ //===----------------------------------------------------------------------===// #include "TableGenBackends.h" -#include "llvm/TableGen/Error.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include diff --git a/clang/utils/TableGen/ClangSACheckersEmitter.cpp b/clang/utils/TableGen/ClangSACheckersEmitter.cpp index 36012dbf70791b743479a58386358e00b78b9ce1..dcb3cac3850beae53b476c764cb8ebecda01c639 100644 --- a/clang/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/clang/utils/TableGen/ClangSACheckersEmitter.cpp @@ -1,4 +1,4 @@ -//=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*- +//===-- ClangSACheckersEmitter.cpp - Generate SA checkers tables ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,7 +15,6 @@ #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include #include using namespace llvm; @@ -28,10 +27,9 @@ static std::string getPackageFullName(const Record *R, StringRef Sep = "."); static std::string getParentPackageFullName(const Record *R, StringRef Sep = ".") { - std::string name; if (const DefInit *DI = dyn_cast(R->getValueInit("ParentPackage"))) - name = getPackageFullName(DI->getDef(), Sep); - return name; + return getPackageFullName(DI->getDef(), Sep); + return ""; } static std::string getPackageFullName(const Record *R, StringRef Sep) { @@ -52,10 +50,10 @@ static std::string getCheckerFullName(const Record *R, StringRef Sep = ".") { return name; } -static std::string getStringValue(const Record &R, StringRef field) { +static StringRef getStringValue(const Record &R, StringRef field) { if (const StringInit *SI = dyn_cast(R.getValueInit(field))) - return std::string(SI->getValue()); - return std::string(); + return SI->getValue(); + return ""; } // Calculates the integer value representing the BitsInit object @@ -93,7 +91,7 @@ static std::string getCheckerDocs(const Record &R) { /// Retrieves the type from a CmdOptionTypeEnum typed Record object. Note that /// the class itself has to be modified for adding a new option type in /// CheckerBase.td. -static std::string getCheckerOptionType(const Record &R) { +static StringRef getCheckerOptionType(const Record &R) { if (const BitsInit *BI = R.getValueAsBitsInit("Type")) { switch(getValueFromBitsInit(BI, R)) { case 0: @@ -110,7 +108,7 @@ static std::string getCheckerOptionType(const Record &R) { return ""; } -static std::string getDevelopmentStage(const Record &R) { +static StringRef getDevelopmentStage(const Record &R) { if (const BitsInit *BI = R.getValueAsBitsInit("DevelopmentStage")) { switch(getValueFromBitsInit(BI, R)) { case 0: @@ -179,8 +177,6 @@ void clang::EmitClangSACheckers(const RecordKeeper &Records, raw_ostream &OS) { ArrayRef packages = Records.getAllDerivedDefinitions("Package"); - using SortedRecords = StringMap; - OS << "// This file is automatically generated. Do not edit this file by " "hand.\n"; @@ -191,16 +187,13 @@ void clang::EmitClangSACheckers(const RecordKeeper &Records, raw_ostream &OS) { OS << "\n" "#ifdef GET_PACKAGES\n"; { - SortedRecords sortedPackages; - for (unsigned i = 0, e = packages.size(); i != e; ++i) - sortedPackages[getPackageFullName(packages[i])] = packages[i]; - - for (SortedRecords::iterator - I = sortedPackages.begin(), E = sortedPackages.end(); I != E; ++I) { - const Record &R = *I->second; - + StringMap sortedPackages; + for (const Record *Package : packages) + sortedPackages[getPackageFullName(Package)] = Package; + + for (const auto &[_, R] : sortedPackages) { OS << "PACKAGE(" << "\""; - OS.write_escaped(getPackageFullName(&R)) << '\"'; + OS.write_escaped(getPackageFullName(R)) << '\"'; OS << ")\n"; } } @@ -225,7 +218,6 @@ void clang::EmitClangSACheckers(const RecordKeeper &Records, raw_ostream &OS) { OS << "\n" "#ifdef GET_PACKAGE_OPTIONS\n"; for (const Record *Package : packages) { - if (Package->isValueUnset("PackageOptions")) continue; @@ -250,9 +242,9 @@ void clang::EmitClangSACheckers(const RecordKeeper &Records, raw_ostream &OS) { OS << "\n" "#ifdef GET_CHECKERS\n" "\n"; - for (const Record *checker : checkers) { + for (const Record *checker : checkers) printChecker(OS, *checker); - } + OS << "\n" "#endif // GET_CHECKERS\n" "\n"; diff --git a/clang/utils/TableGen/ClangSyntaxEmitter.cpp b/clang/utils/TableGen/ClangSyntaxEmitter.cpp index 4098a5e88e682076f2be80bf3fed3badb4df3029..a519ab6d4dda47592633756fc36cc8c44fe922ff 100644 --- a/clang/utils/TableGen/ClangSyntaxEmitter.cpp +++ b/clang/utils/TableGen/ClangSyntaxEmitter.cpp @@ -1,4 +1,4 @@ -//===- ClangSyntaxEmitter.cpp - Generate clang Syntax Tree nodes ----------===// +//===-- ClangSyntaxEmitter.cpp - Generate clang Syntax Tree nodes ---------===// // // The LLVM Compiler Infrastructure // @@ -116,13 +116,13 @@ struct SyntaxConstraint { } else if (R.isSubClassOf("AnyToken")) { NodeType = "Leaf"; } else if (R.isSubClassOf("NodeType")) { - NodeType = R.getName().str(); + NodeType = R.getName(); } else { assert(false && "Unhandled Syntax kind"); } } - std::string NodeType; + StringRef NodeType; // optional and leaf types also go here, once we want to use them. }; diff --git a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp index 41a2d0cd066fef656aea2160d7a95da7823886ca..37039361cfc22837a2a87853199a5c56ee92d7a6 100644 --- a/clang/utils/TableGen/ClangTypeNodesEmitter.cpp +++ b/clang/utils/TableGen/ClangTypeNodesEmitter.cpp @@ -1,4 +1,4 @@ -//=== ClangTypeNodesEmitter.cpp - Generate type node tables -----*- C++ -*-===// +//===-- ClangTypeNodesEmitter.cpp - Generate type node tables -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -52,8 +52,6 @@ #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include -#include #include using namespace llvm; diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 51e570944b49b6a4f3de5307b756d12a2c2aa5c7..8ebd0bb800feff1e219df2bd45521528118d6dc1 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -1,4 +1,4 @@ -//===- MveEmitter.cpp - Generate arm_mve.h for use with clang -*- C++ -*-=====// +//===-- MveEmitter.cpp - Generate arm_mve.h for use with clang ------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -471,7 +471,7 @@ private: public: virtual ~Result() = default; - using Scope = std::map; + using Scope = std::map>; virtual void genCode(raw_ostream &OS, CodeGenParamAllocator &) const = 0; virtual bool hasIntegerConstantValue() const { return false; } virtual uint32_t integerConstantValue() const { return 0; } @@ -1278,7 +1278,7 @@ Result::Ptr EmitterBase::getCodeForDagArg(const DagInit *D, unsigned ArgNum, if (!isa(Arg)) PrintFatalError( "dag operator argument should not have both a value and a name"); - auto it = Scope.find(std::string(Name)); + auto it = Scope.find(Name); if (it == Scope.end()) PrintFatalError("unrecognized variable name '" + Name + "'"); return it->second; diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp index 68ca31e27e0a41faf896bb8061d4b10d7663218b..d7d649dd2456d58b4d897da3e741459a9bdb279e 100644 --- a/clang/utils/TableGen/NeonEmitter.cpp +++ b/clang/utils/TableGen/NeonEmitter.cpp @@ -1,4 +1,4 @@ -//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===// +//===-- NeonEmitter.cpp - Generate arm_neon.h for use with clang ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -101,7 +101,8 @@ enum EltType { Float16, Float32, Float64, - BFloat16 + BFloat16, + MFloat8 // Not used by Sema or CodeGen in Clang }; } // end namespace NeonTypeFlags @@ -143,14 +144,7 @@ class Type { private: TypeSpec TS; - enum TypeKind { - Void, - Float, - SInt, - UInt, - Poly, - BFloat16 - }; + enum TypeKind { Void, Float, SInt, UInt, Poly, BFloat16, MFloat8 }; TypeKind Kind; bool Immediate, Constant, Pointer; // ScalarForMangling and NoManglingQ are really not suited to live here as @@ -203,6 +197,7 @@ public: bool isLong() const { return isInteger() && ElementBitwidth == 64; } bool isVoid() const { return Kind == Void; } bool isBFloat16() const { return Kind == BFloat16; } + bool isMFloat8() const { return Kind == MFloat8; } unsigned getNumElements() const { return Bitwidth / ElementBitwidth; } unsigned getSizeInBits() const { return Bitwidth; } unsigned getElementSizeInBits() const { return ElementBitwidth; } @@ -657,6 +652,8 @@ std::string Type::str() const { S += "float"; else if (isBFloat16()) S += "bfloat"; + else if (isMFloat8()) + S += "mfloat"; else S += "int"; @@ -699,6 +696,9 @@ std::string Type::builtin_str() const { else if (isBFloat16()) { assert(ElementBitwidth == 16 && "BFloat16 can only be 16 bits"); S += "y"; + } else if (isMFloat8()) { + assert(ElementBitwidth == 8 && "MFloat8 can only be 8 bits"); + S += "m"; } else switch (ElementBitwidth) { case 16: S += "h"; break; @@ -758,6 +758,10 @@ unsigned Type::getNeonEnum() const { Base = (unsigned)NeonTypeFlags::BFloat16; } + if (isMFloat8()) { + Base = (unsigned)NeonTypeFlags::MFloat8; + } + if (Bitwidth == 128) Base |= (unsigned)NeonTypeFlags::QuadFlag; if (isInteger() && !isSigned()) @@ -779,6 +783,8 @@ Type Type::fromTypedefName(StringRef Name) { T.Kind = Poly; } else if (Name.consume_front("bfloat")) { T.Kind = BFloat16; + } else if (Name.consume_front("mfloat")) { + T.Kind = MFloat8; } else { assert(Name.starts_with("int")); Name = Name.drop_front(3); @@ -879,6 +885,10 @@ void Type::applyTypespec(bool &Quad) { Kind = BFloat16; ElementBitwidth = 16; break; + case 'm': + Kind = MFloat8; + ElementBitwidth = 8; + break; default: llvm_unreachable("Unhandled type code!"); } @@ -993,6 +1003,9 @@ std::string Intrinsic::getInstTypeCode(Type T, ClassKind CK) const { if (T.isBFloat16()) return "bf16"; + if (T.isMFloat8()) + return "mfp8"; + if (T.isPoly()) typeCode = 'p'; else if (T.isInteger()) @@ -1030,7 +1043,7 @@ std::string Intrinsic::getBuiltinTypeStr() { Type RetT = getReturnType(); if ((LocalCK == ClassI || LocalCK == ClassW) && RetT.isScalar() && - !RetT.isFloating() && !RetT.isBFloat16()) + !RetT.isFloating() && !RetT.isBFloat16() && !RetT.isMFloat8()) RetT.makeInteger(RetT.getElementSizeInBits(), false); // Since the return value must be one type, return a vector type of the @@ -2270,7 +2283,7 @@ static void emitNeonTypeDefs(const std::string& types, raw_ostream &OS) { for (auto &TS : TDTypeVec) { bool IsA64 = false; Type T(TS, "."); - if (T.isDouble()) + if (T.isDouble() || T.isMFloat8()) IsA64 = true; if (InIfdef && !IsA64) { @@ -2282,15 +2295,20 @@ static void emitNeonTypeDefs(const std::string& types, raw_ostream &OS) { InIfdef = true; } - if (T.isPoly()) + if (T.isMFloat8()) + OS << "typedef __MFloat8x"; + else if (T.isPoly()) OS << "typedef __attribute__((neon_polyvector_type("; else OS << "typedef __attribute__((neon_vector_type("; Type T2 = T; T2.makeScalar(); - OS << T.getNumElements() << "))) "; - OS << T2.str(); + OS << T.getNumElements(); + if (T.isMFloat8()) + OS << "_t "; + else + OS << "))) " << T2.str(); OS << " " << T.str() << ";\n"; } if (InIfdef) @@ -2303,7 +2321,7 @@ static void emitNeonTypeDefs(const std::string& types, raw_ostream &OS) { for (auto &TS : TDTypeVec) { bool IsA64 = false; Type T(TS, "."); - if (T.isDouble()) + if (T.isDouble() || T.isMFloat8()) IsA64 = true; if (InIfdef && !IsA64) { @@ -2588,9 +2606,7 @@ void NeonEmitter::runVectorTypes(raw_ostream &OS) { OS << "typedef __fp16 float16_t;\n"; OS << "#if defined(__aarch64__) || defined(__arm64ec__)\n"; - OS << "typedef __MFloat8_t __mfp8;\n"; - OS << "typedef __MFloat8x8_t mfloat8x8_t;\n"; - OS << "typedef __MFloat8x16_t mfloat8x16_t;\n"; + OS << "typedef __mfp8 mfloat8_t;\n"; OS << "typedef double float64_t;\n"; OS << "#endif\n\n"; @@ -2648,7 +2664,7 @@ __arm_set_fpm_lscale2(fpm_t __fpm, uint64_t __scale) { )"; - emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQd", OS); + emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlmQmhQhfQfdQd", OS); emitNeonTypeDefs("bQb", OS); OS << "#endif // __ARM_NEON_TYPES_H\n"; diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index aecca0f5df8d9399bddf36b150c9699c9dbdbb29..68d7831c117458d733242c17bef421d3abbc5f9c 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -1,4 +1,4 @@ -//===- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang -----===// +//===-- RISCVVEmitter.cpp - Generate riscv_vector.h for use with clang ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -16,15 +16,12 @@ #include "clang/Support/RISCVVIntrinsicUtils.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" -#include #include using namespace llvm; diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp index c9bf5d3ddf146ad4bbbc3fa01ff9f1e53340879c..e8883488f32356be277c1cf24f5edc3122891f53 100644 --- a/clang/utils/TableGen/SveEmitter.cpp +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -1,8 +1,8 @@ -//===- SveEmitter.cpp - Generate arm_sve.h for use with clang -*- C++ -*-===// +//===-- SveEmitter.cpp - Generate arm_sve.h for use with clang ------------===// // -// 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 +// 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 // //===----------------------------------------------------------------------===// // @@ -33,7 +33,6 @@ #include #include #include -#include #include #include diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp index 39c178bc4f9baf5b587b0326aa9d51e0395f9324..6e2bd0c9f819b88924ac668d7fbce94bfe902f97 100644 --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -1,4 +1,4 @@ -//===- TableGen.cpp - Top-Level TableGen implementation for Clang ---------===// +//===-- TableGen.cpp - Top-Level TableGen implementation for Clang --------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,13 +10,12 @@ // //===----------------------------------------------------------------------===// -#include "TableGenBackends.h" // Declares all backends. #include "ASTTableGen.h" +#include "TableGenBackends.h" // Declares all backends. #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" -#include "llvm/TableGen/Error.h" #include "llvm/TableGen/Main.h" #include "llvm/TableGen/Record.h" diff --git a/clang/utils/analyzer/exploded-graph-rewriter.py b/clang/utils/analyzer/exploded-graph-rewriter.py index 5eaa7738103f795059fa5b9f913ac3cf16ef2b09..eca0f17beb40a02487d7b800e1bca1327268a726 100755 --- a/clang/utils/analyzer/exploded-graph-rewriter.py +++ b/clang/utils/analyzer/exploded-graph-rewriter.py @@ -86,6 +86,8 @@ class ProgramPoint: if json_pp["location"] is not None else None ) + elif self.kind == "CallEnter": + self.callee_decl = json_pp.get("callee_decl", "None") elif self.kind == "BlockEntrance": self.block_id = json_pp["block_id"] @@ -618,6 +620,13 @@ class DotDumpVisitor: '%s' '[B%d]' % (color, p.kind, p.block_id) ) + elif p.kind == "CallEnter": + self._dump( + '' + '' + '%s' + '%s' % (color, p.kind, p.callee_decl) + ) else: # TODO: Print more stuff for other kinds of points. self._dump( diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 793e7006822cc11e4b7cb2230cbb12a9bdf96ff0..ca2ca5398bb8739e56842f4c1a9fb54ff0562794 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -289,7 +289,7 @@ conformance.

Clang 9 - TS 18661 Integration + TS 18661 Integration N2314 @@ -319,6 +319,10 @@ conformance.

N2931 No + + N2754 + No + Preprocessor line numbers unspecified N2322 @@ -626,11 +630,6 @@ conformance.

N2701 Yes - - Quantum exponent of NaN (version 2) - N2754 - Unknown - The noreturn attribute N2764 diff --git a/compiler-rt/lib/asan/asan_descriptions.cpp b/compiler-rt/lib/asan/asan_descriptions.cpp index caec79313e22ffefd03428391409b0e8c4cb936e..c9f3e4d682d9590f83122c9a53e1ba36f6e53529 100644 --- a/compiler-rt/lib/asan/asan_descriptions.cpp +++ b/compiler-rt/lib/asan/asan_descriptions.cpp @@ -45,6 +45,9 @@ void DescribeThread(AsanThreadContext *context) { } context->announced = true; + InternalScopedString str; + str.AppendF("Thread %s", AsanThreadIdAndName(context).c_str()); + AsanThreadContext *parent_context = context->parent_tid == kInvalidTid ? nullptr @@ -52,12 +55,7 @@ void DescribeThread(AsanThreadContext *context) { // `context->parent_tid` may point to reused slot. Check `unique_id` which // is always smaller for the parent, always greater for a new user. - if (context->unique_id <= parent_context->unique_id) - parent_context = nullptr; - - InternalScopedString str; - str.AppendF("Thread %s", AsanThreadIdAndName(context).c_str()); - if (!parent_context) { + if (!parent_context || context->unique_id <= parent_context->unique_id) { str.Append(" created by unknown thread\n"); Printf("%s", str.data()); return; diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64.c b/compiler-rt/lib/builtins/cpu_model/aarch64.c index ea2da23a95278fd581136b170aa4161292fcfc21..74e5e01b66c5475f6ae77334b42038511cd574ba 100644 --- a/compiler-rt/lib/builtins/cpu_model/aarch64.c +++ b/compiler-rt/lib/builtins/cpu_model/aarch64.c @@ -48,6 +48,8 @@ _Bool __aarch64_have_lse_atomics #elif defined(__linux__) && __has_include() #include "aarch64/hwcap.inc" #include "aarch64/lse_atomics/getauxval.inc" +#elif defined(_WIN32) +#include "aarch64/lse_atomics/windows.inc" #else // When unimplemented, we leave __aarch64_have_lse_atomics initialized to false. #endif @@ -76,6 +78,8 @@ struct { #elif defined(__linux__) && __has_include() #include "aarch64/fmv/mrs.inc" #include "aarch64/fmv/getauxval.inc" +#elif defined(_WIN32) +#include "aarch64/fmv/windows.inc" #else #include "aarch64/fmv/unimplemented.inc" #endif diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/windows.inc b/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/windows.inc new file mode 100644 index 0000000000000000000000000000000000000000..2ca18242fba3e4ff3aa258a8a77d2c6a0461dffe --- /dev/null +++ b/compiler-rt/lib/builtins/cpu_model/aarch64/fmv/windows.inc @@ -0,0 +1,85 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#ifndef PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE 43 +#endif +#ifndef PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE 44 +#endif +#ifndef PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE 45 +#endif +#ifndef PF_ARM_SVE_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_INSTRUCTIONS_AVAILABLE 46 +#endif +#ifndef PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE 47 +#endif +#ifndef PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE 50 +#endif +#ifndef PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE 55 +#endif +#ifndef PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE 56 +#endif +#ifndef PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE 57 +#endif +#ifndef PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE 58 +#endif +#ifndef PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE 59 +#endif + +void __init_cpu_features_resolver(unsigned long hwcap, + const __ifunc_arg_t *arg) {} + +void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) { + if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED)) + return; + +#define setCPUFeature(F) features |= 1ULL << F + + uint64_t features = 0; + + setCPUFeature(FEAT_INIT); + setCPUFeature(FEAT_FP); + + // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) { + setCPUFeature(FEAT_SHA2); + setCPUFeature(FEAT_PMULL); + } + + static const struct ProcessFeatureToFeatMap_t { + int WinApiFeature; + enum CPUFeatures CPUFeature; + } FeatMap[] = { + {PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE, FEAT_CRC}, + {PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE, FEAT_LSE}, + {PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE, FEAT_DOTPROD}, + {PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE, FEAT_JSCVT}, + {PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE, FEAT_RCPC}, + {PF_ARM_SVE_INSTRUCTIONS_AVAILABLE, FEAT_SVE}, + {PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE, FEAT_SVE2}, + {PF_ARM_SVE_PMULL128_INSTRUCTIONS_AVAILABLE, FEAT_SVE_PMULL128}, + {PF_ARM_SVE_SHA3_INSTRUCTIONS_AVAILABLE, FEAT_SVE_SHA3}, + {PF_ARM_SVE_SM4_INSTRUCTIONS_AVAILABLE, FEAT_SVE_SM4}, + {PF_ARM_SVE_F32MM_INSTRUCTIONS_AVAILABLE, FEAT_SVE_F32MM}, + {PF_ARM_SVE_F64MM_INSTRUCTIONS_AVAILABLE, FEAT_SVE_F64MM}, + // There is no I8MM flag, but when SVE_I8MM is available, I8MM is too. + {PF_ARM_SVE_I8MM_INSTRUCTIONS_AVAILABLE, FEAT_I8MM}, + }; + + for (size_t I = 0, E = sizeof(FeatMap) / sizeof(FeatMap[0]); I != E; ++I) + if (IsProcessorFeaturePresent(FeatMap[I].WinApiFeature)) + setCPUFeature(FeatMap[I].CPUFeature); + + __atomic_store(&__aarch64_cpu_features.features, &features, __ATOMIC_RELAXED); +} diff --git a/compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/windows.inc b/compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/windows.inc new file mode 100644 index 0000000000000000000000000000000000000000..fff1593e1fac333499b188d3495eb3e7e8962269 --- /dev/null +++ b/compiler-rt/lib/builtins/cpu_model/aarch64/lse_atomics/windows.inc @@ -0,0 +1,12 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include + +#ifndef PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE +#define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE 34 +#endif + +static void CONSTRUCTOR_ATTRIBUTE init_have_lse_atomics(void) { + if (IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) + __aarch64_have_lse_atomics = true; +} diff --git a/compiler-rt/lib/builtins/cpu_model/cpu_model.h b/compiler-rt/lib/builtins/cpu_model/cpu_model.h index 924ca89cf60f5c4483aee468a1719189a4dcc3e8..3bc4e63c4f25ab85c836b160fb3d774330e46f4e 100644 --- a/compiler-rt/lib/builtins/cpu_model/cpu_model.h +++ b/compiler-rt/lib/builtins/cpu_model/cpu_model.h @@ -31,7 +31,15 @@ // We're choosing init priority 90 to force our constructors to run before any // constructors in the end user application (starting at priority 101). This // value matches the libgcc choice for the same functions. -#define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor(90))) +#ifdef _WIN32 +// Contructor that replaces the ifunc runs currently with prio 10, see +// the LowerIFuncPass. The resolver of FMV depends on the cpu features so set +// the priority to 9. +#define CONSTRUCTOR_PRIORITY 9 +#else +#define CONSTRUCTOR_PRIORITY 90 +#endif +#define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor(CONSTRUCTOR_PRIORITY))) #else // FIXME: For MSVC, we should make a function pointer global in .CRT$X?? so that // this runs during initialization. diff --git a/compiler-rt/lib/builtins/cpu_model/x86.c b/compiler-rt/lib/builtins/cpu_model/x86.c index bfa478c4427a5bf420a15fa2afc8a2545ee12e00..3315dceb7f5622ca6dc3088fd7070dc0780fa92b 100644 --- a/compiler-rt/lib/builtins/cpu_model/x86.c +++ b/compiler-rt/lib/builtins/cpu_model/x86.c @@ -103,6 +103,7 @@ enum ProcessorSubtypes { INTEL_COREI7_ARROWLAKE_S, INTEL_COREI7_PANTHERLAKE, AMDFAM1AH_ZNVER5, + INTEL_COREI7_DIAMONDRAPIDS, CPU_SUBTYPE_MAX }; @@ -600,6 +601,19 @@ static const char *getIntelProcessorTypeAndSubtype(unsigned Family, break; } break; + case 19: + switch (Model) { + // Diamond Rapids: + case 0x01: + CPU = "diamondrapids"; + *Type = INTEL_COREI7; + *Subtype = INTEL_COREI7_DIAMONDRAPIDS; + break; + + default: // Unknown family 19 CPU. + break; + } + break; default: break; // Unknown. } diff --git a/compiler-rt/lib/builtins/trunctfbf2.c b/compiler-rt/lib/builtins/trunctfbf2.c index 3d47b13bdf5c2cf4eace3c9f50e4f419674c45e6..cd3c761aa62f315a71fc9e88416ffabf08207aba 100644 --- a/compiler-rt/lib/builtins/trunctfbf2.c +++ b/compiler-rt/lib/builtins/trunctfbf2.c @@ -15,4 +15,4 @@ COMPILER_RT_ABI dst_t __trunctfbf2(src_t a) { return __truncXfYf2__(a); } -#endif \ No newline at end of file +#endif diff --git a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h index d92b51052194275d41bcfdbb25a2a78a43cf7561..e8011014c2331d7ce9de7832daa1a5a84a2de04e 100644 --- a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h +++ b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h @@ -200,6 +200,9 @@ #undef SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID #define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID 0 +#undef SANITIZER_INTERCEPT_TIMER_CREATE +#define SANITIZER_INTERCEPT_TIMER_CREATE 0 + #undef SANITIZER_INTERCEPT_GETITIMER #define SANITIZER_INTERCEPT_GETITIMER 0 diff --git a/compiler-rt/lib/lsan/lsan_common.cpp b/compiler-rt/lib/lsan/lsan_common.cpp index 5c44c000ae577b0c36326dc3d706e26230ad299c..7ab9e4ff2ac9fde1664ea94e9a7df68be630ce8e 100644 --- a/compiler-rt/lib/lsan/lsan_common.cpp +++ b/compiler-rt/lib/lsan/lsan_common.cpp @@ -569,7 +569,7 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, PtraceRegistersStatus have_registers = suspended_threads.GetRegistersAndSP(i, ®isters, &sp); if (have_registers != REGISTERS_AVAILABLE) { - Report("Unable to get registers from thread %llu.\n", os_id); + VReport(1, "Unable to get registers from thread %llu.\n", os_id); // If unable to get SP, consider the entire stack to be reachable unless // GetRegistersAndSP failed with ESRCH. if (have_registers == REGISTERS_UNAVAILABLE_FATAL) diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp index 41b99fabe84f4789d3ae179ed3f3bb4aefb812c5..a126dd4fdd55e54528c0221995db4b65ac5c0c3b 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cpp +++ b/compiler-rt/lib/msan/tests/msan_test.cpp @@ -4881,4 +4881,32 @@ TEST(MemorySanitizer, throw_catch) { // pass } } + +#if defined(__GLIBC__) +TEST(MemorySanitizer, timer_create) { + timer_t timer; + EXPECT_POISONED(timer); + int res = timer_create(CLOCK_REALTIME, nullptr, &timer); + ASSERT_EQ(0, res); + EXPECT_NOT_POISONED(timer); + + // Make sure the timer is usable. + struct itimerspec cur_value {}; + cur_value.it_value.tv_sec = 1; + EXPECT_EQ(0, timer_settime(timer, 0, &cur_value, nullptr)); + + struct itimerspec read_value; + EXPECT_POISONED(read_value); + EXPECT_EQ(0, timer_gettime(timer, &read_value)); + EXPECT_NOT_POISONED(read_value); + + timer_t timer2; + EXPECT_POISONED(timer2); + // Use an invalid clock_id to make timer_create fail. + res = timer_create(INT_MAX, nullptr, &timer2); + ASSERT_EQ(-1, res); + EXPECT_POISONED(timer2); + timer_delete(timer); +} +#endif } // namespace diff --git a/compiler-rt/lib/rtsan/rtsan.cpp b/compiler-rt/lib/rtsan/rtsan.cpp index e9f42d3760aa824cb74c47373faeeef58967966e..70edcc546219fa736d7524d3fbc7f74b50d46064 100644 --- a/compiler-rt/lib/rtsan/rtsan.cpp +++ b/compiler-rt/lib/rtsan/rtsan.cpp @@ -62,8 +62,12 @@ static void OnViolation(const BufferedStackTrace &stack, if (UNLIKELY(is_stack_novel)) { IncrementUniqueErrorCount(); - PrintDiagnostics(info); - stack.Print(); + { + ScopedErrorReportLock l; + PrintDiagnostics(info); + stack.Print(); + PrintErrorSummary(info, stack); + } handle.inc_use_count_unsafe(); } diff --git a/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp b/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp index ecba30d2ab8df52d3ce3c51358c5affc8cabb366..f13d3db101d487f42ff6ae8b156c6c4b78832df6 100644 --- a/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp +++ b/compiler-rt/lib/rtsan/rtsan_diagnostics.cpp @@ -39,20 +39,22 @@ public: }; } // namespace +static const char *GetErrorTypeStr(const DiagnosticsInfo &info) { + switch (info.type) { + case DiagnosticsInfoType::InterceptedCall: + return "unsafe-library-call"; + case DiagnosticsInfoType::BlockingCall: + return "blocking-call"; + } + CHECK(false); + return "(unknown error)"; +} + static void PrintError(const Decorator &decorator, const DiagnosticsInfo &info) { - const auto ErrorTypeStr = [&info]() -> const char * { - switch (info.type) { - case DiagnosticsInfoType::InterceptedCall: - return "unsafe-library-call"; - case DiagnosticsInfoType::BlockingCall: - return "blocking-call"; - } - return "(unknown error)"; - }; Printf("%s", decorator.Error()); - Report("ERROR: RealtimeSanitizer: %s\n", ErrorTypeStr()); + Report("ERROR: RealtimeSanitizer: %s\n", GetErrorTypeStr(info)); } static void PrintReason(const Decorator &decorator, @@ -78,10 +80,16 @@ static void PrintReason(const Decorator &decorator, } void __rtsan::PrintDiagnostics(const DiagnosticsInfo &info) { - ScopedErrorReportLock l; + ScopedErrorReportLock::CheckLocked(); Decorator d; PrintError(d, info); PrintReason(d, info); Printf("%s", d.Default()); } + +void __rtsan::PrintErrorSummary(const DiagnosticsInfo &info, + const BufferedStackTrace &stack) { + ScopedErrorReportLock::CheckLocked(); + ReportErrorSummary(GetErrorTypeStr(info), &stack); +} diff --git a/compiler-rt/lib/rtsan/rtsan_diagnostics.h b/compiler-rt/lib/rtsan/rtsan_diagnostics.h index f8a6b8a954a24ac98a94ff93cf79d53ab1904d9a..1138e61eb5df4c99cb860cd18f84d9140d8ba34e 100644 --- a/compiler-rt/lib/rtsan/rtsan_diagnostics.h +++ b/compiler-rt/lib/rtsan/rtsan_diagnostics.h @@ -30,4 +30,6 @@ struct DiagnosticsInfo { }; void PrintDiagnostics(const DiagnosticsInfo &info); +void PrintErrorSummary(const DiagnosticsInfo &info, + const __sanitizer::BufferedStackTrace &stack); } // namespace __rtsan diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index c3fcd4f2da85ce9f1baf812d6fa7bbb4f5d05bf0..73448cfc117884d13b351dbf2207475953a937ff 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -42,6 +42,7 @@ void OSSpinLockLock(volatile OSSpinLock *__lock); #endif #include +#include #include #include #include @@ -60,8 +61,11 @@ struct DlsymAlloc : public DlSymAllocator { // Filesystem INTERCEPTOR(int, open, const char *path, int oflag, ...) { - // TODO Establish whether we should intercept here if the flag contains - // O_NONBLOCK + // We do not early exit if O_NONBLOCK is set. + // O_NONBLOCK **does not prevent the syscall** it simply sets the FD to be in + // nonblocking mode, which is a different concept than our + // [[clang::nonblocking]], and is not rt-safe. This behavior was confirmed + // using Instruments on Darwin with a simple test program __rtsan_notify_intercepted_call("open"); if (OpenReadsVaArgs(oflag)) { @@ -77,8 +81,7 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) { #if SANITIZER_INTERCEPT_OPEN64 INTERCEPTOR(int, open64, const char *path, int oflag, ...) { - // TODO Establish whether we should intercept here if the flag contains - // O_NONBLOCK + // See comment above about O_NONBLOCK __rtsan_notify_intercepted_call("open64"); if (OpenReadsVaArgs(oflag)) { @@ -97,8 +100,7 @@ INTERCEPTOR(int, open64, const char *path, int oflag, ...) { #endif // SANITIZER_INTERCEPT_OPEN64 INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) { - // TODO Establish whether we should intercept here if the flag contains - // O_NONBLOCK + // See comment above about O_NONBLOCK __rtsan_notify_intercepted_call("openat"); if (OpenReadsVaArgs(oflag)) { @@ -114,8 +116,7 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) { #if SANITIZER_INTERCEPT_OPENAT64 INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) { - // TODO Establish whether we should intercept here if the flag contains - // O_NONBLOCK + // See comment above about O_NONBLOCK __rtsan_notify_intercepted_call("openat64"); if (OpenReadsVaArgs(oflag)) { @@ -134,8 +135,7 @@ INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) { #endif // SANITIZER_INTERCEPT_OPENAT64 INTERCEPTOR(int, creat, const char *path, mode_t mode) { - // TODO Establish whether we should intercept here if the flag contains - // O_NONBLOCK + // See comment above about O_NONBLOCK __rtsan_notify_intercepted_call("creat"); const int result = REAL(creat)(path, mode); return result; @@ -143,8 +143,7 @@ INTERCEPTOR(int, creat, const char *path, mode_t mode) { #if SANITIZER_INTERCEPT_CREAT64 INTERCEPTOR(int, creat64, const char *path, mode_t mode) { - // TODO Establish whether we should intercept here if the flag contains - // O_NONBLOCK + // See comment above about O_NONBLOCK __rtsan_notify_intercepted_call("creat64"); const int result = REAL(creat64)(path, mode); return result; @@ -317,6 +316,31 @@ INTERCEPTOR(ssize_t, writev, int fd, const struct iovec *iov, int iovcnt) { return REAL(writev)(fd, iov, iovcnt); } +INTERCEPTOR(off_t, lseek, int fd, off_t offset, int whence) { + __rtsan_notify_intercepted_call("lseek"); + return REAL(lseek)(fd, offset, whence); +} + +#if SANITIZER_INTERCEPT_LSEEK64 +INTERCEPTOR(off64_t, lseek64, int fd, off64_t offset, int whence) { + __rtsan_notify_intercepted_call("lseek64"); + return REAL(lseek64)(fd, offset, whence); +} +#define RTSAN_MAYBE_INTERCEPT_LSEEK64 INTERCEPT_FUNCTION(lseek64) +#else +#define RTSAN_MAYBE_INTERCEPT_LSEEK64 +#endif // SANITIZER_INTERCEPT_LSEEK64 + +INTERCEPTOR(int, dup, int oldfd) { + __rtsan_notify_intercepted_call("dup"); + return REAL(dup)(oldfd); +} + +INTERCEPTOR(int, dup2, int oldfd, int newfd) { + __rtsan_notify_intercepted_call("dup2"); + return REAL(dup2)(oldfd, newfd); +} + // Concurrency #if SANITIZER_APPLE #pragma clang diagnostic push @@ -614,6 +638,114 @@ INTERCEPTOR(int, shutdown, int socket, int how) { return REAL(shutdown)(socket, how); } +// I/O Multiplexing + +INTERCEPTOR(int, poll, struct pollfd *fds, nfds_t nfds, int timeout) { + __rtsan_notify_intercepted_call("poll"); + return REAL(poll)(fds, nfds, timeout); +} + +#if !SANITIZER_APPLE +// FIXME: This should work on all unix systems, even Mac, but currently +// it is showing some weird error while linking +// error: declaration of 'select' has a different language linkage +INTERCEPTOR(int, select, int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) { + __rtsan_notify_intercepted_call("select"); + return REAL(select)(nfds, readfds, writefds, exceptfds, timeout); +} +#define RTSAN_MAYBE_INTERCEPT_SELECT INTERCEPT_FUNCTION(select) +#else +#define RTSAN_MAYBE_INTERCEPT_SELECT +#endif // !SANITIZER_APPLE + +INTERCEPTOR(int, pselect, int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timespec *timeout, + const sigset_t *sigmask) { + __rtsan_notify_intercepted_call("pselect"); + return REAL(pselect)(nfds, readfds, writefds, exceptfds, timeout, sigmask); +} + +#if SANITIZER_INTERCEPT_EPOLL +INTERCEPTOR(int, epoll_create, int size) { + __rtsan_notify_intercepted_call("epoll_create"); + return REAL(epoll_create)(size); +} + +INTERCEPTOR(int, epoll_create1, int flags) { + __rtsan_notify_intercepted_call("epoll_create1"); + return REAL(epoll_create1)(flags); +} + +INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd, + struct epoll_event *event) { + __rtsan_notify_intercepted_call("epoll_ctl"); + return REAL(epoll_ctl)(epfd, op, fd, event); +} + +INTERCEPTOR(int, epoll_wait, int epfd, struct epoll_event *events, + int maxevents, int timeout) { + __rtsan_notify_intercepted_call("epoll_wait"); + return REAL(epoll_wait)(epfd, events, maxevents, timeout); +} + +INTERCEPTOR(int, epoll_pwait, int epfd, struct epoll_event *events, + int maxevents, int timeout, const sigset_t *sigmask) { + __rtsan_notify_intercepted_call("epoll_pwait"); + return REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask); +} +#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE INTERCEPT_FUNCTION(epoll_create) +#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE1 INTERCEPT_FUNCTION(epoll_create1) +#define RTSAN_MAYBE_INTERCEPT_EPOLL_CTL INTERCEPT_FUNCTION(epoll_ctl) +#define RTSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait) +#define RTSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait) +#else +#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE +#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE1 +#define RTSAN_MAYBE_INTERCEPT_EPOLL_CTL +#define RTSAN_MAYBE_INTERCEPT_EPOLL_WAIT +#define RTSAN_MAYBE_INTERCEPT_EPOLL_PWAIT +#endif // SANITIZER_INTERCEPT_EPOLL + +#if SANITIZER_INTERCEPT_KQUEUE +INTERCEPTOR(int, kqueue, void) { + __rtsan_notify_intercepted_call("kqueue"); + return REAL(kqueue)(); +} + +INTERCEPTOR(int, kevent, int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, + const struct timespec *timeout) { + __rtsan_notify_intercepted_call("kevent"); + return REAL(kevent)(kq, changelist, nchanges, eventlist, nevents, timeout); +} + +INTERCEPTOR(int, kevent64, int kq, const struct kevent64_s *changelist, + int nchanges, struct kevent64_s *eventlist, int nevents, + unsigned int flags, const struct timespec *timeout) { + __rtsan_notify_intercepted_call("kevent64"); + return REAL(kevent64)(kq, changelist, nchanges, eventlist, nevents, flags, + timeout); +} +#define RTSAN_MAYBE_INTERCEPT_KQUEUE INTERCEPT_FUNCTION(kqueue) +#define RTSAN_MAYBE_INTERCEPT_KEVENT INTERCEPT_FUNCTION(kevent) +#define RTSAN_MAYBE_INTERCEPT_KEVENT64 INTERCEPT_FUNCTION(kevent64) +#else +#define RTSAN_MAYBE_INTERCEPT_KQUEUE +#define RTSAN_MAYBE_INTERCEPT_KEVENT +#define RTSAN_MAYBE_INTERCEPT_KEVENT64 +#endif // SANITIZER_INTERCEPT_KQUEUE + +INTERCEPTOR(int, pipe, int pipefd[2]) { + __rtsan_notify_intercepted_call("pipe"); + return REAL(pipe)(pipefd); +} + +INTERCEPTOR(int, mkfifo, const char *pathname, mode_t mode) { + __rtsan_notify_intercepted_call("mkfifo"); + return REAL(mkfifo)(pathname, mode); +} + // Preinit void __rtsan::InitializeInterceptors() { INTERCEPT_FUNCTION(calloc); @@ -660,6 +792,10 @@ void __rtsan::InitializeInterceptors() { RTSAN_MAYBE_INTERCEPT_CREAT64; INTERCEPT_FUNCTION(puts); INTERCEPT_FUNCTION(fputs); + INTERCEPT_FUNCTION(lseek); + RTSAN_MAYBE_INTERCEPT_LSEEK64; + INTERCEPT_FUNCTION(dup); + INTERCEPT_FUNCTION(dup2); #if SANITIZER_APPLE INTERCEPT_FUNCTION(OSSpinLockLock); @@ -698,6 +834,21 @@ void __rtsan::InitializeInterceptors() { INTERCEPT_FUNCTION(sendto); INTERCEPT_FUNCTION(shutdown); INTERCEPT_FUNCTION(socket); + + RTSAN_MAYBE_INTERCEPT_SELECT; + INTERCEPT_FUNCTION(pselect); + INTERCEPT_FUNCTION(poll); + RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE; + RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE1; + RTSAN_MAYBE_INTERCEPT_EPOLL_CTL; + RTSAN_MAYBE_INTERCEPT_EPOLL_WAIT; + RTSAN_MAYBE_INTERCEPT_EPOLL_PWAIT; + RTSAN_MAYBE_INTERCEPT_KQUEUE; + RTSAN_MAYBE_INTERCEPT_KEVENT; + RTSAN_MAYBE_INTERCEPT_KEVENT64; + + INTERCEPT_FUNCTION(pipe); + INTERCEPT_FUNCTION(mkfifo); } #endif // SANITIZER_POSIX diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index d0ae12c9bea447a7f238c3efb9421d6275713259..3e14346f33c7caa8a41ae6484f6816d157976177 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -28,8 +28,18 @@ #include #endif +#if SANITIZER_INTERCEPT_EPOLL +#include +#endif + +#if SANITIZER_INTERCEPT_KQUEUE +#include +#include +#endif + #include #include +#include #include #include #include @@ -357,6 +367,24 @@ private: int fd = -1; }; +TEST_F(RtsanOpenedFileTest, LseekDiesWhenRealtime) { + auto Func = [this]() { lseek(GetOpenFd(), 0, SEEK_SET); }; + ExpectRealtimeDeath(Func, MAYBE_APPEND_64("lseek")); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanOpenedFileTest, DupDiesWhenRealtime) { + auto Func = [this]() { dup(GetOpenFd()); }; + ExpectRealtimeDeath(Func, "dup"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanOpenedFileTest, Dup2DiesWhenRealtime) { + auto Func = [this]() { dup2(GetOpenFd(), 0); }; + ExpectRealtimeDeath(Func, "dup2"); + ExpectNonRealtimeSurvival(Func); +} + TEST_F(RtsanOpenedFileTest, FreadDiesWhenRealtime) { auto Func = [this]() { char c{}; @@ -779,4 +807,175 @@ TEST(TestRtsanInterceptors, ShutdownOnASocketDiesWhenRealtime) { ExpectNonRealtimeSurvival(Func); } +/* + I/O Multiplexing +*/ + +TEST(TestRtsanInterceptors, PollDiesWhenRealtime) { + struct pollfd fds[1]; + fds[0].fd = 0; + fds[0].events = POLLIN; + + auto Func = [&fds]() { poll(fds, 1, 0); }; + + ExpectRealtimeDeath(Func, "poll"); + ExpectNonRealtimeSurvival(Func); +} + +#if !SANITIZER_APPLE +// FIXME: This should work on Darwin as well +// see the comment near the interceptor +TEST(TestRtsanInterceptors, SelectDiesWhenRealtime) { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(0, &readfds); + struct timeval timeout = {0, 0}; + + auto Func = [&readfds, &timeout]() { + select(1, &readfds, nullptr, nullptr, &timeout); + }; + ExpectRealtimeDeath(Func, "select"); + ExpectNonRealtimeSurvival(Func); +} +#endif + +TEST(TestRtsanInterceptors, PSelectDiesWhenRealtime) { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(0, &readfds); + struct timespec timeout = {0, 0}; + + auto Func = [&]() { + pselect(1, &readfds, nullptr, nullptr, &timeout, nullptr); + }; + ExpectRealtimeDeath(Func, "pselect"); + ExpectNonRealtimeSurvival(Func); +} + +#if SANITIZER_INTERCEPT_EPOLL +TEST(TestRtsanInterceptors, EpollCreateDiesWhenRealtime) { + auto Func = []() { epoll_create(1); }; + ExpectRealtimeDeath(Func, "epoll_create"); + ExpectNonRealtimeSurvival(Func); +} + +TEST(TestRtsanInterceptors, EpollCreate1DiesWhenRealtime) { + auto Func = []() { epoll_create1(EPOLL_CLOEXEC); }; + ExpectRealtimeDeath(Func, "epoll_create1"); + ExpectNonRealtimeSurvival(Func); +} + +class EpollTest : public ::testing::Test { +protected: + void SetUp() override { + epfd = epoll_create1(EPOLL_CLOEXEC); + ASSERT_GE(epfd, 0); + } + + void TearDown() override { + if (epfd >= 0) + close(epfd); + } + + int GetEpollFd() { return epfd; } + +private: + int epfd = -1; +}; + +TEST_F(EpollTest, EpollCtlDiesWhenRealtime) { + auto Func = [this]() { + struct epoll_event event = {.events = EPOLLIN, .data = {.fd = 0}}; + epoll_ctl(GetEpollFd(), EPOLL_CTL_ADD, 0, &event); + }; + ExpectRealtimeDeath(Func, "epoll_ctl"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(EpollTest, EpollWaitDiesWhenRealtime) { + auto Func = [this]() { + struct epoll_event events[1]; + epoll_wait(GetEpollFd(), events, 1, 0); + }; + + ExpectRealtimeDeath(Func, "epoll_wait"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(EpollTest, EpollPWaitDiesWhenRealtime) { + auto Func = [this]() { + struct epoll_event events[1]; + epoll_pwait(GetEpollFd(), events, 1, 0, nullptr); + }; + + ExpectRealtimeDeath(Func, "epoll_pwait"); + ExpectNonRealtimeSurvival(Func); +} +#endif // SANITIZER_INTERCEPT_EPOLL + +#if SANITIZER_INTERCEPT_KQUEUE +TEST(TestRtsanInterceptors, KqueueDiesWhenRealtime) { + auto Func = []() { kqueue(); }; + ExpectRealtimeDeath(Func, "kqueue"); + ExpectNonRealtimeSurvival(Func); +} + +class KqueueTest : public ::testing::Test { +protected: + void SetUp() override { + kq = kqueue(); + ASSERT_GE(kq, 0); + } + + void TearDown() override { + if (kq >= 0) + close(kq); + } + + int GetKqueueFd() { return kq; } + +private: + int kq = -1; +}; + +TEST_F(KqueueTest, KeventDiesWhenRealtime) { + struct kevent event; + EV_SET(&event, 0, EVFILT_READ, EV_ADD, 0, 0, nullptr); + struct timespec timeout = {0, 0}; + + auto Func = [this, event, timeout]() { + kevent(GetKqueueFd(), &event, 1, nullptr, 0, &timeout); + }; + + ExpectRealtimeDeath(Func, "kevent"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(KqueueTest, Kevent64DiesWhenRealtime) { + struct kevent64_s event; + EV_SET64(&event, 0, EVFILT_READ, EV_ADD, 0, 0, 0, 0, 0); + struct timespec timeout = {0, 0}; + + auto Func = [this, event, timeout]() { + kevent64(GetKqueueFd(), &event, 1, nullptr, 0, 0, &timeout); + }; + + ExpectRealtimeDeath(Func, "kevent64"); + ExpectNonRealtimeSurvival(Func); +} +#endif // SANITIZER_INTERCEPT_KQUEUE + +TEST(TestRtsanInterceptors, MkfifoDiesWhenRealtime) { + auto Func = []() { mkfifo("/tmp/rtsan_test_fifo", 0); }; + ExpectRealtimeDeath(Func, "mkfifo"); + ExpectNonRealtimeSurvival(Func); +} + +TEST(TestRtsanInterceptors, PipeDiesWhenRealtime) { + int fds[2]; + auto Func = [&fds]() { pipe(fds); }; + ExpectRealtimeDeath(Func, "pipe"); + ExpectNonRealtimeSurvival(Func); +} + #endif // SANITIZER_POSIX diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h index 0b0bdb07041e5bad7b8b5973dab670a9f086fa96..51ac1b6ae497576c0df725180758daf7ad2dd000 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h @@ -185,9 +185,10 @@ class SizeClassAllocator64 { // recoverable. if (UNLIKELY(!EnsureFreeArraySpace(region, region_beg, new_num_freed_chunks))) { - Report("FATAL: Internal error: %s's allocator exhausted the free list " - "space for size class %zd (%zd bytes).\n", SanitizerToolName, - class_id, ClassIdToSize(class_id)); + Report( + "FATAL: Internal error: %s's allocator exhausted the free list " + "space for size class %zu (%zu bytes).\n", + SanitizerToolName, class_id, ClassIdToSize(class_id)); Die(); } for (uptr i = 0; i < n_chunks; i++) @@ -763,8 +764,9 @@ class SizeClassAllocator64 { if (!region->exhausted) { region->exhausted = true; Printf("%s: Out of memory. ", SanitizerToolName); - Printf("The process has exhausted %zuMB for size class %zu.\n", - kRegionSize >> 20, ClassIdToSize(class_id)); + Printf( + "The process has exhausted %zu MB for size class %zu (%zu bytes).\n", + kRegionSize >> 20, class_id, ClassIdToSize(class_id)); } return true; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index b8627f8557afe29c10a37211fbc7f7cf6fc8221b..99fa737adfaf26aed56f1eddb8bc89a260ce7ea7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2289,6 +2289,61 @@ INTERCEPTOR(int, pthread_getcpuclockid, uptr thread, #define INIT_CLOCK_GETCPUCLOCKID #endif +#if SANITIZER_INTERCEPT_TIMER_CREATE +INTERCEPTOR(int, timer_create, __sanitizer_clockid_t clockid, void *sevp, + __sanitizer_timer_t *timer) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, timer_create, clockid, sevp, timer); + int res = REAL(timer_create)(clockid, sevp, timer); + if (!res && timer) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, timer, sizeof *timer); + } + return res; +} + +INTERCEPTOR(int, timer_delete, __sanitizer_timer_t timer) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, timer_delete, timer); + int res = REAL(timer_delete)(timer); + return res; +} + +INTERCEPTOR(int, timer_gettime, __sanitizer_timer_t timer, + struct __sanitizer_itimerspec *curr_value) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, timer_gettime, timer, curr_value); + int res = REAL(timer_gettime)(timer, curr_value); + if (!res && curr_value) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, sizeof *curr_value); + } + return res; +} + +INTERCEPTOR(int, timer_settime, __sanitizer_timer_t timer, int flags, + const struct __sanitizer_itimerspec *new_value, + struct __sanitizer_itimerspec *old_value) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, timer_settime, timer, flags, new_value, + old_value); + int res = REAL(timer_settime)(timer, flags, new_value, old_value); + if (!res) { + if (new_value) + COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, sizeof *new_value); + if (old_value) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, sizeof *old_value); + } + return res; +} + +# define INIT_TIMER_CREATE \ + COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_create, "GLIBC_2.3.3"); \ + COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_delete, "GLIBC_2.3.3"); \ + COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_gettime, "GLIBC_2.3.3"); \ + COMMON_INTERCEPT_FUNCTION_GLIBC_VER_MIN(timer_settime, "GLIBC_2.3.3"); +#else +# define INIT_TIMER_CREATE +#endif + #if SANITIZER_INTERCEPT_GETITIMER INTERCEPTOR(int, getitimer, int which, void *curr_value) { void *ctx; @@ -10266,6 +10321,7 @@ static void InitializeCommonInterceptors() { INIT_SETPWENT; INIT_CLOCK_GETTIME; INIT_CLOCK_GETCPUCLOCKID; + INIT_TIMER_CREATE; INIT_GETITIMER; INIT_TIME; INIT_GLOB; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 8b1850f85010cf8020c61097eb0794982e5a6e13..04b095dca904ab38b517097db193467c03ae5f0b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -164,33 +164,56 @@ void SetSigProcMask(__sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) { CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, set, oldset)); } +# if SANITIZER_LINUX +// Deletes the specified signal from newset, if it is not present in oldset +// Equivalently: newset[signum] = newset[signum] & oldset[signum] +static void KeepUnblocked(__sanitizer_sigset_t &newset, + __sanitizer_sigset_t &oldset, int signum) { + // FIXME: https://github.com/google/sanitizers/issues/1816 + if (SANITIZER_ANDROID || !internal_sigismember(&oldset, signum)) + internal_sigdelset(&newset, signum); +} +# endif + // Block asynchronous signals void BlockSignals(__sanitizer_sigset_t *oldset) { - __sanitizer_sigset_t set; - internal_sigfillset(&set); -# if SANITIZER_LINUX && !SANITIZER_ANDROID + __sanitizer_sigset_t newset; + internal_sigfillset(&newset); + +# if SANITIZER_LINUX + __sanitizer_sigset_t currentset; + +# if !SANITIZER_ANDROID + // FIXME: https://github.com/google/sanitizers/issues/1816 + SetSigProcMask(NULL, ¤tset); + // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked // on any thread, setuid call hangs. // See test/sanitizer_common/TestCases/Linux/setuid.c. - internal_sigdelset(&set, 33); -# endif -# if SANITIZER_LINUX + KeepUnblocked(newset, currentset, 33); +# endif // !SANITIZER_ANDROID + // Seccomp-BPF-sandboxed processes rely on SIGSYS to handle trapped syscalls. // If this signal is blocked, such calls cannot be handled and the process may // hang. - internal_sigdelset(&set, 31); + KeepUnblocked(newset, currentset, 31); +# if !SANITIZER_ANDROID // Don't block synchronous signals - internal_sigdelset(&set, SIGSEGV); - internal_sigdelset(&set, SIGBUS); - internal_sigdelset(&set, SIGILL); - internal_sigdelset(&set, SIGTRAP); - internal_sigdelset(&set, SIGABRT); - internal_sigdelset(&set, SIGFPE); - internal_sigdelset(&set, SIGPIPE); -# endif + // but also don't unblock signals that the user had deliberately blocked. + // FIXME: https://github.com/google/sanitizers/issues/1816 + KeepUnblocked(newset, currentset, SIGSEGV); + KeepUnblocked(newset, currentset, SIGBUS); + KeepUnblocked(newset, currentset, SIGILL); + KeepUnblocked(newset, currentset, SIGTRAP); + KeepUnblocked(newset, currentset, SIGABRT); + KeepUnblocked(newset, currentset, SIGFPE); + KeepUnblocked(newset, currentset, SIGPIPE); +# endif //! SANITIZER_ANDROID + +# endif // SANITIZER_LINUX - SetSigProcMask(&set, oldset); + SetSigProcMask(&newset, oldset); } ScopedBlockSignals::ScopedBlockSignals(__sanitizer_sigset_t *copy) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 3fd6b595ef197f8080b445e6e3d018eed632c84b..1f78b1af8e2c6f8912528a177374f2537791fcd4 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -210,6 +210,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_PREAD64 (SI_GLIBC || SI_SOLARIS32) #define SANITIZER_INTERCEPT_PWRITE64 (SI_GLIBC || SI_SOLARIS32) +#define SANITIZER_INTERCEPT_LSEEK64 (SI_GLIBC || SI_SOLARIS32) + #define SANITIZER_INTERCEPT_READV SI_POSIX #define SANITIZER_INTERCEPT_WRITEV SI_POSIX @@ -256,6 +258,9 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, (SI_FREEBSD || SI_NETBSD || SI_LINUX || SI_SOLARIS) #define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID \ (SI_LINUX || SI_FREEBSD || SI_NETBSD) +// TODO: This should be SI_POSIX, adding glibc first until I have time +// to verify all timer_t typedefs on other platforms. +#define SANITIZER_INTERCEPT_TIMER_CREATE SI_GLIBC #define SANITIZER_INTERCEPT_GETITIMER SI_POSIX #define SANITIZER_INTERCEPT_TIME SI_POSIX #define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS) @@ -339,6 +344,8 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment, #define SANITIZER_INTERCEPT_GETGROUPS SI_POSIX #define SANITIZER_INTERCEPT_POLL SI_POSIX #define SANITIZER_INTERCEPT_PPOLL SI_LINUX_NOT_ANDROID || SI_SOLARIS +#define SANITIZER_INTERCEPT_EPOLL (SI_LINUX) +#define SANITIZER_INTERCEPT_KQUEUE (SI_FREEBSD || SI_NETBSD || SI_MAC) #define SANITIZER_INTERCEPT_WORDEXP \ (SI_FREEBSD || SI_NETBSD || (SI_MAC && !SI_IOS) || SI_LINUX_NOT_ANDROID || \ SI_SOLARIS) 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 e8c81aa8e281637b74f7fff5660e8d07b0089412..7d98f8e9a9d801238c50e0381b8c283ee07aea6b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -389,6 +389,16 @@ typedef long __sanitizer_time_t; typedef long __sanitizer_suseconds_t; +struct __sanitizer_timespec { + __sanitizer_time_t tv_sec; /* seconds */ + u64 tv_nsec; /* nanoseconds */ +}; + +struct __sanitizer_itimerspec { + struct __sanitizer_timespec it_interval; /* timer period */ + struct __sanitizer_timespec it_value; /* timer expiration */ +}; + struct __sanitizer_timeval { __sanitizer_time_t tv_sec; __sanitizer_suseconds_t tv_usec; @@ -1517,6 +1527,10 @@ extern const int si_SEGV_ACCERR; #define SIGACTION_SYMNAME sigaction +# if SANITIZER_LINUX +typedef void *__sanitizer_timer_t; +# endif + #endif // SANITIZER_LINUX || SANITIZER_APPLE #endif diff --git a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt index 2b4c15125263a9c40e903bc7c77ab3710b72022b..fef8bb772e0e0d17ddc9b8d7628b2c2494940a98 100644 --- a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt @@ -15,6 +15,7 @@ set(SANITIZER_UNITTESTS sanitizer_array_ref_test.cpp sanitizer_atomic_test.cpp sanitizer_bitvector_test.cpp + sanitizer_block_signals.cpp sanitizer_bvgraph_test.cpp sanitizer_chained_origin_depot_test.cpp sanitizer_common_test.cpp diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_block_signals.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_block_signals.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b43648a8aef2304d7c1f13092f7a2d931578fff1 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_block_signals.cpp @@ -0,0 +1,76 @@ +//===-- sanitizer_block_signals.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 +// +//===----------------------------------------------------------------------===// +// +// This file is a part of sanitizer_common unit tests. +// +//===----------------------------------------------------------------------===// +#include +#include + +#include "gtest/gtest.h" +#include "sanitizer_common/sanitizer_linux.h" + +namespace __sanitizer { + +#if SANITIZER_LINUX && !SANITIZER_ANDROID +volatile int received_sig = -1; + +void signal_handler(int signum) { received_sig = signum; } + +TEST(SanitizerCommon, NoBlockSignals) { + // No signals blocked + signal(SIGUSR1, signal_handler); + raise(SIGUSR1); + EXPECT_EQ(received_sig, SIGUSR1); + + received_sig = -1; + signal(SIGPIPE, signal_handler); + raise(SIGPIPE); + EXPECT_EQ(received_sig, SIGPIPE); +} + +TEST(SanitizerCommon, BlockSignalsPlain) { + // ScopedBlockSignals; SIGUSR1 should be blocked but not SIGPIPE + { + __sanitizer_sigset_t sigset = {}; + ScopedBlockSignals block(&sigset); + + received_sig = -1; + signal(SIGUSR1, signal_handler); + raise(SIGUSR1); + EXPECT_EQ(received_sig, -1); + + received_sig = -1; + signal(SIGPIPE, signal_handler); + raise(SIGPIPE); + EXPECT_EQ(received_sig, SIGPIPE); + } + EXPECT_EQ(received_sig, SIGUSR1); +} + +TEST(SanitizerCommon, BlockSignalsExceptPipe) { + // Manually block SIGPIPE; ScopedBlockSignals should not unblock this + sigset_t block_sigset; + sigemptyset(&block_sigset); + sigaddset(&block_sigset, SIGPIPE); + sigprocmask(SIG_BLOCK, &block_sigset, NULL); + { + __sanitizer_sigset_t sigset = {}; + ScopedBlockSignals block(&sigset); + + received_sig = -1; + signal(SIGPIPE, signal_handler); + raise(SIGPIPE); + EXPECT_EQ(received_sig, -1); + } + sigprocmask(SIG_UNBLOCK, &block_sigset, NULL); + EXPECT_EQ(received_sig, SIGPIPE); +} +#endif // SANITIZER_LINUX && !SANITIZER_ANDROID + +} // namespace __sanitizer diff --git a/compiler-rt/test/orc/TestCases/Darwin/Generic/trivial-cxx-constructor.cpp b/compiler-rt/test/orc/TestCases/Darwin/Generic/trivial-cxx-constructor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3c9cad6342bc6e62ba17a92d0aa9173b4c7e377 --- /dev/null +++ b/compiler-rt/test/orc/TestCases/Darwin/Generic/trivial-cxx-constructor.cpp @@ -0,0 +1,17 @@ +// RUN: %clangxx -c -o %t %s +// RUN: %llvm_jitlink %t +// +// REQUIRES: system-darwin && host-arch-compatible + +static int x = 1; + +class Init { +public: + Init() { x = 0; } +}; + +static Init I; + +int main(int argc, char *argv[]) { + return x; +} diff --git a/compiler-rt/test/profile/ContinuousSyncMode/basic.c b/compiler-rt/test/profile/ContinuousSyncMode/basic.c index 142a47a71ad8ac05f6a6f6d683a184af48e5a1ee..e8bd087a0f59d8d78a56372834298866a3a1847b 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/basic.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/basic.c @@ -1,11 +1,15 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} -// RUN: %clang -fprofile-instr-generate -fcoverage-mapping -o %t.exe %s +// RUN: %clang_profgen_cont -fcoverage-mapping -o %t.exe %s // RUN: echo "garbage" > %t.profraw // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe // RUN: llvm-profdata show --counts --all-functions %t.profraw | FileCheck %s -check-prefix=CHECK-COUNTS // RUN: llvm-profdata merge -o %t.profdata %t.profraw -// RUN: llvm-cov report %t.exe -instr-profile %t.profdata | FileCheck %s -check-prefix=CHECK-COVERAGE +// +// COM: The "report" and "show" commands of llvm-cov are not supported on AIX. +// RUN: %if !target={{.*aix.*}} %{ \ +// RUN: llvm-cov report %t.exe -instr-profile %t.profdata | FileCheck %s -check-prefix=CHECK-COVERAGE \ +// RUN: %} // CHECK-COUNTS: Counters: // CHECK-COUNTS-NEXT: main: diff --git a/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c b/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c index d70e11991e180af03bf61d948787b9eb7b22978a..40a0cc5ffd6886f493a8956c592fa073c72a1144 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c @@ -1,6 +1,6 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} -// RUN: %clang_pgogen -o %t.exe %s +// RUN: %clang_pgogen_cont -o %t.exe %s // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe %t.profraw // RUN: env LLVM_PROFILE_FILE="%t%c.profraw" %run %t.exe %t.profraw // RUN: env LLVM_PROFILE_FILE="%t.profraw%c" %run %t.exe %t.profraw diff --git a/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c b/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c index d2afe7048f37f4468a6098b4e806882569748a6e..d171badbf4d332baef45adc6c0f763e8965e569e 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c @@ -1,6 +1,6 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} -// RUN: %clang_profgen -fcoverage-mapping -fcoverage-mcdc -O3 -o %t.exe %s +// RUN: %clang_profgen_cont -fcoverage-mapping -fcoverage-mcdc -O3 -o %t.exe %s // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe 3 3 // RUN: llvm-profdata show --text --all-functions %t.profraw | FileCheck %s diff --git a/compiler-rt/test/profile/ContinuousSyncMode/image-with-no-counters.c b/compiler-rt/test/profile/ContinuousSyncMode/image-with-no-counters.c index f30e2255b2289bcf95826d895db51b2c07e24f17..4313ad30b7273f0d37d45a53ab7faeec4df897cb 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/image-with-no-counters.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/image-with-no-counters.c @@ -1,8 +1,8 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} // RUN: echo "static void dead_code(void) {}" > %t.dso.c -// RUN: %clang_profgen -fcoverage-mapping -O3 -dynamiclib -o %t.dso.dylib %t.dso.c -// RUN: %clang_profgen -fcoverage-mapping -O3 -o %t.exe %s %t.dso.dylib +// RUN: %clang_profgen_cont -fcoverage-mapping -O3 %shared_lib_flag -o %t.dso.dylib %t.dso.c +// RUN: %clang_profgen_cont -fcoverage-mapping -O3 -o %t.exe %s %t.dso.dylib // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe 2>&1 | count 0 // RUN: llvm-profdata show --counts --all-functions %t.profraw | FileCheck %s diff --git a/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp b/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff05a69a5e7d4d825defcf9c2c2ebe0e5334130c --- /dev/null +++ b/compiler-rt/test/profile/ContinuousSyncMode/multi-threaded.cpp @@ -0,0 +1,29 @@ +// REQUIRES: target={{.*(darwin|aix).*}} + +// RUN: rm -f %t.profraw +// RUN: %clangxx_pgogen_cont -lpthread %s -o %t.exe -mllvm -disable-vp -fprofile-update=atomic +// RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe +// RUN: llvm-profdata show --counts --function=accum %t.profraw | FileCheck %s +// CHECK: Block counts: [100000, 4] + +#include + +int x = 0; +void accum(int n) { + for (int i = 0; i < n; i++) + x += i; // don't care about accuracy, no need for atomic. +} + +int main() { + int init_value = 10000; + auto t1 = std::thread(accum, 1*init_value); + auto t2 = std::thread(accum, 2*init_value); + auto t3 = std::thread(accum, 3*init_value); + auto t4 = std::thread(accum, 4*init_value); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + return !x; +} diff --git a/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c b/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c index b3c33f339713c2aa93134195e6e6d909d2f88bc7..54346487a5c7952f8269ac602aebfc5deeb19d3d 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/online-merging.c @@ -1,4 +1,4 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} // Test the online merging mode (%m) along with continuous mode (%c). // @@ -8,9 +8,9 @@ // Create two DSOs and a driver program that uses them. // RUN: echo "void dso1(void) {}" > dso1.c // RUN: echo "void dso2(void) {}" > dso2.c -// RUN: %clang_pgogen -dynamiclib -o %t.dir/dso1.dylib dso1.c -mllvm -instrprof-atomic-counter-update-all=1 -// RUN: %clang_pgogen -dynamiclib -o %t.dir/dso2.dylib dso2.c -mllvm -instrprof-atomic-counter-update-all=1 -// RUN: %clang_pgogen -o main.exe %s %t.dir/dso1.dylib %t.dir/dso2.dylib -mllvm -instrprof-atomic-counter-update-all=1 +// RUN: %clang_pgogen_cont %shared_lib_flag -o %t.dir/dso1.dylib dso1.c -fprofile-update=atomic +// RUN: %clang_pgogen_cont %shared_lib_flag -o %t.dir/dso2.dylib dso2.c -fprofile-update=atomic +// RUN: %clang_pgogen_cont -o main.exe %s %t.dir/dso1.dylib %t.dir/dso2.dylib -fprofile-update=atomic // // === Round 1 === // Test merging+continuous mode without any file contention. diff --git a/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c b/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c index b2b95f41f2bdf20c3f61d9bfd9e24bc60ed25bcc..309b685a95c5bc0e2c52257d4c0974693f5a29e3 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/pid-substitution.c @@ -1,7 +1,7 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} // RUN: rm -rf %t.dir && mkdir -p %t.dir -// RUN: %clang_pgogen -o %t.exe %s +// RUN: %clang_pgogen_cont -o %t.exe %s // // Note: %%p is needed here, not %p, because of lit's path substitution. // RUN: env LLVM_PROFILE_FILE="%t.dir/%c-%%p" %run %t.exe diff --git a/compiler-rt/test/profile/ContinuousSyncMode/reset-default-profile.c b/compiler-rt/test/profile/ContinuousSyncMode/reset-default-profile.c index 75af7684161c9b403e0ba1ca18898b94e088c3bd..fb35d77c43428047993d61398f8ee93a893c8d66 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/reset-default-profile.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/reset-default-profile.c @@ -1,4 +1,4 @@ -// REQUIRES: darwin || linux +// REQUIRES: target={{.*(darwin|linux|aix).*}} // Test when LLVM_PROFILE_FILE is set incorrectly, it should fall backs to use default.profraw without runtime error. diff --git a/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c b/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c index e6d5fd31ab1b600846517f65da67223eca9809fc..106e12e4e3b6ebbfe4742e959b7f7a3cd563dc72 100644 --- a/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c +++ b/compiler-rt/test/profile/ContinuousSyncMode/set-filename.c @@ -1,6 +1,6 @@ -// REQUIRES: darwin +// REQUIRES: target={{.*(darwin|aix).*}} -// RUN: %clang_pgogen -o %t.exe %s +// RUN: %clang_pgogen_cont -o %t.exe %s // RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe %t.profraw %t.bad #include diff --git a/compiler-rt/test/profile/lit.cfg.py b/compiler-rt/test/profile/lit.cfg.py index bb5e28d87bb0f96b2fe096a5096eb65cabb6cefa..72a389eaf0dfb295d4d46b5ab0a2a74d7eea1667 100644 --- a/compiler-rt/test/profile/lit.cfg.py +++ b/compiler-rt/test/profile/lit.cfg.py @@ -30,6 +30,9 @@ if ( target_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple)) +# Whether continous profile collection (%c) requires runtime counter relocation on this platform +runtime_reloc = bool(config.host_os in ["AIX"]) + if config.host_os in ["Linux"]: extra_link_flags = ["-ldl"] elif target_is_msvc: @@ -94,6 +97,14 @@ config.substitutions.append( config.substitutions.append( ("%clang_profgen=", build_invocation(clang_cflags) + " -fprofile-instr-generate=") ) +config.substitutions.append( + ( + "%clang_profgen_cont ", + build_invocation(clang_cflags) + + " -fprofile-instr-generate " + + ("-mllvm -runtime-counter-relocation " if runtime_reloc else ""), + ) +) config.substitutions.append( ( "%clangxx_profgen ", @@ -113,12 +124,28 @@ config.substitutions.append( config.substitutions.append( ("%clang_pgogen=", build_invocation(clang_cflags) + " -fprofile-generate=") ) +config.substitutions.append( + ( + "%clang_pgogen_cont ", + build_invocation(clang_cflags) + + " -fprofile-generate " + + ("-mllvm -runtime-counter-relocation " if runtime_reloc else ""), + ) +) config.substitutions.append( ("%clangxx_pgogen ", build_invocation(clang_cxxflags) + " -fprofile-generate ") ) config.substitutions.append( ("%clangxx_pgogen=", build_invocation(clang_cxxflags) + " -fprofile-generate=") ) +config.substitutions.append( + ( + "%clangxx_pgogen_cont ", + build_invocation(clang_cxxflags) + + " -fprofile-generate " + + ("-mllvm -runtime-counter-relocation " if runtime_reloc else ""), + ) +) config.substitutions.append( ("%clang_cspgogen ", build_invocation(clang_cflags) + " -fcs-profile-generate ") @@ -166,6 +193,10 @@ if config.host_os not in [ ]: config.unsupported = True +config.substitutions.append( + ("%shared_lib_flag", "-dynamiclib" if (config.host_os == "Darwin") else "-shared") +) + if config.host_os in ["AIX"]: config.available_features.add("system-aix") exclude_unsupported_files_for_aix(config.test_source_root) diff --git a/compiler-rt/test/rtsan/report_error_summary.cpp b/compiler-rt/test/rtsan/report_error_summary.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9da7f217f61bfabc872b913d51be142bc2409faf --- /dev/null +++ b/compiler-rt/test/rtsan/report_error_summary.cpp @@ -0,0 +1,32 @@ +// RUN: %clangxx -fsanitize=realtime %s -o %t +// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s + +// RUN: %clangxx -DTEST_CUSTOM_HANDLER=1 -fsanitize=realtime %s -o %t +// RUN: not %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-CUSTOM-HANDLER + +// UNSUPPORTED: ios + +// Intent: Make sure we support ReporErrorSummary, including custom handlers + +#include +#include + +#ifdef TEST_CUSTOM_HANDLER +extern "C" void __sanitizer_report_error_summary(const char *error_summary) { + fprintf(stderr, "%s %s\n", "In custom handler! ", error_summary); +} +#endif + +int blocking_call() [[clang::blocking]] { return 0; } + +int main() [[clang::nonblocking]] { + void *ptr = malloc(2); + blocking_call(); + + printf("ptr: %p\n", ptr); // ensure we don't optimize out the malloc +} + +// CHECK: SUMMARY: RealtimeSanitizer: unsafe-library-call +// CHECK: SUMMARY: RealtimeSanitizer: blocking-call + +// CHECK-CUSTOM-HANDLER: In custom handler! SUMMARY: RealtimeSanitizer: unsafe-library-call diff --git a/flang/CODE_OWNERS.TXT b/flang/Maintainers.txt similarity index 100% rename from flang/CODE_OWNERS.TXT rename to flang/Maintainers.txt diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index dc68f160f5d924ca36584416db4122f408c60710..fe7fee97bc78e55566df6cfd8c73822905b8f96f 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -475,9 +475,9 @@ public: READ_FEATURE(OmpDoacross::Source) READ_FEATURE(OmpDoacrossClause) READ_FEATURE(OmpDependenceType) - READ_FEATURE(OmpDependenceType::Type) + READ_FEATURE(OmpDependenceType::Value) READ_FEATURE(OmpTaskDependenceType) - READ_FEATURE(OmpTaskDependenceType::Type) + READ_FEATURE(OmpTaskDependenceType::Value) READ_FEATURE(OmpIteration) READ_FEATURE(OmpIterationOffset) READ_FEATURE(OmpIterationVector) @@ -495,7 +495,7 @@ public: READ_FEATURE(OmpLinearClause::WithModifier) READ_FEATURE(OmpLinearClause::WithoutModifier) READ_FEATURE(OmpLinearModifier) - READ_FEATURE(OmpLinearModifier::Type) + READ_FEATURE(OmpLinearModifier::Value) READ_FEATURE(OmpLoopDirective) READ_FEATURE(OmpMapClause) READ_FEATURE(OmpMapClause::TypeModifier) @@ -515,7 +515,7 @@ public: READ_FEATURE(OmpReductionCombiner) READ_FEATURE(OmpReductionCombiner::FunctionCombiner) READ_FEATURE(OmpReductionInitializerClause) - READ_FEATURE(OmpReductionOperator) + READ_FEATURE(OmpReductionIdentifier) READ_FEATURE(OmpAllocateClause) READ_FEATURE(OmpAllocateClause::AllocateModifier) READ_FEATURE(OmpAllocateClause::AllocateModifier::Allocator) diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp index d28ed0534d6002639e4d5b4e7e10821bbdf20ed5..c184fdafb5c330ef647b63e026796327e15761e9 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp @@ -218,11 +218,11 @@ void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) { clauseDetails += "modifier=" + std::string{OmpScheduleModifierType::EnumToString(c)} + ";"; } -void OpenMPCounterVisitor::Post(const OmpLinearModifier::Type &c) { +void OpenMPCounterVisitor::Post(const OmpLinearModifier::Value &c) { clauseDetails += "modifier=" + std::string{OmpLinearModifier::EnumToString(c)} + ";"; } -void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Type &c) { +void OpenMPCounterVisitor::Post(const OmpTaskDependenceType::Value &c) { clauseDetails += "type=" + std::string{OmpTaskDependenceType::EnumToString(c)} + ";"; } diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h index 68c52db46e2f0089c8d395ad97e606236834c3c6..6c2d194a88e69aa0630a329cc47478e3b7da9352 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h @@ -72,8 +72,8 @@ struct OpenMPCounterVisitor { void Post(const OmpDefaultmapClause::VariableCategory &c); void Post(const OmpDeviceTypeClause::Type &c); void Post(const OmpScheduleModifierType::ModType &c); - void Post(const OmpLinearModifier::Type &c); - void Post(const OmpTaskDependenceType::Type &c); + void Post(const OmpLinearModifier::Value &c); + void Post(const OmpTaskDependenceType::Value &c); void Post(const OmpMapClause::Type &c); void Post(const OmpScheduleClause::ScheduleType &c); void Post(const OmpIfClause::DirectiveNameModifier &c); diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h index 74edbe44fdbb1ccc8db9331b103ee60894286b47..c6ab846cce2fc009091daf3ea84cff7938518cd1 100644 --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -53,7 +53,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines, NonBindCInteroperability, CudaManaged, CudaUnified, PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy, UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr, - SavedLocalInSpecExpr, PrintNamelist) + SavedLocalInSpecExpr, PrintNamelist, AssumedRankPassedToNonAssumedRank) // Portability and suspicious usage warnings ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable, diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index f547138f5a116c52821a2cbd3a2af98455dc0809..6261a4eec4a5553b9ab9facd47f98151fa803062 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -1103,8 +1103,7 @@ extern template semantics::UnorderedSymbolSet CollectCudaSymbols( bool HasVectorSubscript(const Expr &); // Utilities for attaching the location of the declaration of a symbol -// of interest to a message, if both pointers are non-null. Handles -// the case of USE association gracefully. +// of interest to a message. Handles the case of USE association gracefully. parser::Message *AttachDeclaration(parser::Message &, const Symbol &); parser::Message *AttachDeclaration(parser::Message *, const Symbol &); template @@ -1417,6 +1416,8 @@ common::IgnoreTKRSet GetIgnoreTKR(const Symbol &); std::optional GetDummyArgumentNumber(const Symbol *); +const Symbol *FindAncestorModuleProcedure(const Symbol *symInSubmodule); + } // namespace Fortran::semantics #endif // FORTRAN_EVALUATE_TOOLS_H_ diff --git a/flang/include/flang/Lower/StatementContext.h b/flang/include/flang/Lower/StatementContext.h index 7776edc93ed737a7dd6b0e842d13e0b0caf5a487..eef21d4bae5aab616c74867fd3f549193808bfd4 100644 --- a/flang/include/flang/Lower/StatementContext.h +++ b/flang/include/flang/Lower/StatementContext.h @@ -92,10 +92,13 @@ public: cufs.back().reset(); } + /// Pop the stack top list. + void pop() { cufs.pop_back(); } + /// Make cleanup calls. Pop the stack top list. void finalizeAndPop() { finalizeAndKeep(); - cufs.pop_back(); + pop(); } bool hasCode() const { diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index 09f7b892f1ecbe311adf3e79f86e6abc6219abae..b772c523caba49925547039f1c45dcf38c6995ed 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -215,6 +215,11 @@ public: llvm::ArrayRef lenParams, bool asTarget = false); + /// Create a two dimensional ArrayAttr containing integer data as + /// IntegerAttrs, effectively: ArrayAttr>>. + mlir::ArrayAttr create2DI64ArrayAttr( + llvm::SmallVectorImpl> &intData); + /// Create a temporary using `fir.alloca`. This function does not hoist. /// It is the callers responsibility to set the insertion point if /// hoisting is required. diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index 6b41025eea0780253706eeaf1720e2231b81589c..f073f494b3fb21353e2a6c9dc72606c0db1833ab 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -357,8 +357,8 @@ hlfir::ElementalOp genElementalOp( /// Structure to describe a loop nest. struct LoopNest { - fir::DoLoopOp outerLoop; - fir::DoLoopOp innerLoop; + mlir::Operation *outerOp = nullptr; + mlir::Block *body = nullptr; llvm::SmallVector oneBasedIndices; }; @@ -366,11 +366,13 @@ struct LoopNest { /// \p isUnordered specifies whether the loops in the loop nest /// are unordered. LoopNest genLoopNest(mlir::Location loc, fir::FirOpBuilder &builder, - mlir::ValueRange extents, bool isUnordered = false); + mlir::ValueRange extents, bool isUnordered = false, + bool emitWorkshareLoop = false); inline LoopNest genLoopNest(mlir::Location loc, fir::FirOpBuilder &builder, - mlir::Value shape, bool isUnordered = false) { + mlir::Value shape, bool isUnordered = false, + bool emitWorkshareLoop = false) { return genLoopNest(loc, builder, getIndexExtents(loc, builder, shape), - isUnordered); + isUnordered, emitWorkshareLoop); } /// Inline the body of an hlfir.elemental at the current insertion point diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index f5fb272b4cc3ed28a0bad382c1c9629edbc0ad25..e83d1a42e341331370358bc1e90e4b6890b5f44c 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -290,6 +290,7 @@ struct IntrinsicLibrary { mlir::Value genIeeeQuietCompare(mlir::Type resultType, llvm::ArrayRef); mlir::Value genIeeeReal(mlir::Type, llvm::ArrayRef); + mlir::Value genIeeeRem(mlir::Type, llvm::ArrayRef); mlir::Value genIeeeRint(mlir::Type, llvm::ArrayRef); template void genIeeeSetFlagOrHaltingMode(llvm::ArrayRef); diff --git a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td index d34a8af0394a44b181bea71a365c411c7b39486f..d06587c57d44b65460018cc082be780b3f4cd55f 100644 --- a/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td +++ b/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.td @@ -162,7 +162,7 @@ def cuf_DataTransferOp : cuf_Op<"data_transfer", []> { let arguments = (ins Arg:$src, Arg:$dst, - Optional:$shape, + Optional:$shape, cuf_DataTransferKindAttr:$transfer_kind); let assemblyFormat = [{ diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h index fb7b1d16f62f3ac85813d6adf7ba73ac3de93c1e..f7f0a3067b318afacf23ebfa71014a656b4655a9 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h +++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h @@ -75,6 +75,16 @@ constexpr llvm::StringRef getOptionalAttrName() { return "fir.optional"; } /// Attribute to mark Fortran entities with the TARGET attribute. static constexpr llvm::StringRef getTargetAttrName() { return "fir.target"; } +/// Attribute to mark Fortran entities with the ASYNCHRONOUS attribute. +static constexpr llvm::StringRef getAsynchronousAttrName() { + return "fir.asynchronous"; +} + +/// Attribute to mark Fortran entities with the VOLATILE attribute. +static constexpr llvm::StringRef getVolatileAttrName() { + return "fir.volatile"; +} + /// Attribute to mark that a function argument is a character dummy procedure. /// Character dummy procedure have special ABI constraints. static constexpr llvm::StringRef getCharacterProcedureDummyAttrName() { diff --git a/flang/include/flang/Optimizer/OpenMP/Passes.h b/flang/include/flang/Optimizer/OpenMP/Passes.h index 403d79667bf448d1061d0c976fd6d751529c5931..feb395f1a12dbd8eccd44f1313417cbeb355db7c 100644 --- a/flang/include/flang/Optimizer/OpenMP/Passes.h +++ b/flang/include/flang/Optimizer/OpenMP/Passes.h @@ -25,6 +25,11 @@ namespace flangomp { #define GEN_PASS_REGISTRATION #include "flang/Optimizer/OpenMP/Passes.h.inc" +/// Impelements the logic specified in the 2.8.3 workshare Construct section of +/// the OpenMP standard which specifies what statements or constructs shall be +/// divided into units of work. +bool shouldUseWorkshareLowering(mlir::Operation *op); + } // namespace flangomp #endif // FORTRAN_OPTIMIZER_OPENMP_PASSES_H diff --git a/flang/include/flang/Optimizer/OpenMP/Passes.td b/flang/include/flang/Optimizer/OpenMP/Passes.td index c070bc22ff20ccce8235d0267c872c2058299848..37977334c1e9ed70b28d0c81f7996bbb54796551 100644 --- a/flang/include/flang/Optimizer/OpenMP/Passes.td +++ b/flang/include/flang/Optimizer/OpenMP/Passes.td @@ -50,4 +50,9 @@ def FunctionFilteringPass : Pass<"omp-function-filtering"> { ]; } +// Needs to be scheduled on Module as we create functions in it +def LowerWorkshare : Pass<"lower-workshare", "::mlir::ModuleOp"> { + let summary = "Lower workshare construct"; +} + #endif //FORTRAN_OPTIMIZER_OPENMP_PASSES diff --git a/flang/include/flang/Optimizer/Passes/Pipelines.h b/flang/include/flang/Optimizer/Passes/Pipelines.h index 3b54ac388385879b060e40f5d60bb0110fce17a9..55fafc2e6b36fe9c1c80faceae80427ad3eacafe 100644 --- a/flang/include/flang/Optimizer/Passes/Pipelines.h +++ b/flang/include/flang/Optimizer/Passes/Pipelines.h @@ -123,7 +123,8 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, /// \param optLevel - optimization level used for creating FIR optimization /// passes pipeline void createHLFIRToFIRPassPipeline( - mlir::PassManager &pm, llvm::OptimizationLevel optLevel = defaultOptLevel); + mlir::PassManager &pm, bool enableOpenMP, + llvm::OptimizationLevel optLevel = defaultOptLevel); /// Create a pass pipeline for handling certain OpenMP transformations needed /// prior to FIR lowering. diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index d89713a9fc0b977bfc100172030a7e668bcfd12d..1db41fa7972bf15f42cde433e97fef287af962f9 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -424,7 +424,7 @@ def AssumedRankOpConversion : Pass<"fir-assumed-rank-op", "mlir::ModuleOp"> { def CUFOpConversion : Pass<"cuf-convert", "mlir::ModuleOp"> { let summary = "Convert some CUF operations to runtime calls"; let dependentDialects = [ - "fir::FIROpsDialect" + "fir::FIROpsDialect", "mlir::gpu::GPUDialect" ]; } diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 4bbf9777a54ccb6efa871696e58899ae41a645d4..63fddc424182b2ded92614335d6f7c6458b1251f 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -236,6 +236,7 @@ public: NODE(parser, CUFKernelDoConstruct) NODE(CUFKernelDoConstruct, StarOrExpr) NODE(CUFKernelDoConstruct, Directive) + NODE(CUFKernelDoConstruct, LaunchConfiguration) NODE(parser, CUFReduction) NODE(parser, CycleStmt) NODE(parser, DataComponentDefStmt) @@ -476,7 +477,7 @@ public: NODE(parser, ObjectDecl) NODE(parser, OldParameterStmt) NODE(parser, OmpIteratorSpecifier) - NODE(parser, OmpIteratorModifier) + NODE(parser, OmpIterator) NODE(parser, OmpAffinityClause) NODE(parser, OmpAlignedClause) NODE(parser, OmpAtomic) @@ -505,15 +506,16 @@ public: NODE(parser, OmpDeclareTargetSpecifier) NODE(parser, OmpDeclareTargetWithClause) NODE(parser, OmpDeclareTargetWithList) + NODE(parser, OmpDeclareMapperSpecifier) NODE(parser, OmpDefaultClause) NODE_ENUM(OmpDefaultClause, Type) NODE(parser, OmpDefaultmapClause) NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior) NODE_ENUM(OmpDefaultmapClause, VariableCategory) NODE(parser, OmpDependenceType) - NODE_ENUM(OmpDependenceType, Type) + NODE_ENUM(OmpDependenceType, Value) NODE(parser, OmpTaskDependenceType) - NODE_ENUM(OmpTaskDependenceType, Type) + NODE_ENUM(OmpTaskDependenceType, Value) NODE(parser, OmpIterationOffset) NODE(parser, OmpIteration) NODE(parser, OmpIterationVector) @@ -541,9 +543,10 @@ public: NODE(OmpLinearClause, WithModifier) NODE(OmpLinearClause, WithoutModifier) NODE(parser, OmpLinearModifier) - NODE_ENUM(OmpLinearModifier, Type) + NODE_ENUM(OmpLinearModifier, Value) NODE(parser, OmpLoopDirective) NODE(parser, OmpMapClause) + NODE(parser, OmpMapperIdentifier) NODE_ENUM(OmpMapClause, TypeModifier) NODE_ENUM(OmpMapClause, Type) static std::string GetNodeName(const llvm::omp::Clause &x) { @@ -571,7 +574,7 @@ public: NODE(parser, OmpReductionCombiner) NODE(OmpReductionCombiner, FunctionCombiner) NODE(parser, OmpReductionInitializerClause) - NODE(parser, OmpReductionOperator) + NODE(parser, OmpReductionIdentifier) NODE(parser, OmpAllocateClause) NODE(OmpAllocateClause, AllocateModifier) NODE(OmpAllocateClause::AllocateModifier, Allocator) @@ -620,6 +623,7 @@ public: NODE(parser, OpenMPDeclareReductionConstruct) NODE(parser, OpenMPDeclareSimdConstruct) NODE(parser, OpenMPDeclareTargetConstruct) + NODE(parser, OpenMPDeclareMapperConstruct) NODE(parser, OmpMemoryOrderClause) NODE(parser, OmpAtomicClause) NODE(parser, OmpAtomicClauseList) diff --git a/flang/include/flang/Parser/parse-tree-visitor.h b/flang/include/flang/Parser/parse-tree-visitor.h index 81d01dbdd65cc9f0bd3780e52abf85b22595d1ec..e1ea4d459f4a602058d81c57efd046a5efad89c5 100644 --- a/flang/include/flang/Parser/parse-tree-visitor.h +++ b/flang/include/flang/Parser/parse-tree-visitor.h @@ -29,881 +29,918 @@ namespace Fortran::parser { -// Default case for visitation of non-class data members, strings, and -// any other non-decomposable values. -template -std::enable_if_t || std::is_same_v || - std::is_same_v> -Walk(const A &x, V &visitor) { - if (visitor.Pre(x)) { - visitor.Post(x); - } -} -template -std::enable_if_t || std::is_same_v || - std::is_same_v> -Walk(A &x, M &mutator) { - if (mutator.Pre(x)) { - mutator.Post(x); - } -} +template void Walk(const A &x, V &visitor); +template void Walk(A &x, M &mutator); -template void Walk(const format::ControlEditDesc &, V &); -template void Walk(format::ControlEditDesc &, M &); -template void Walk(const format::DerivedTypeDataEditDesc &, V &); -template void Walk(format::DerivedTypeDataEditDesc &, M &); -template void Walk(const format::FormatItem &, V &); -template void Walk(format::FormatItem &, M &); -template void Walk(const format::FormatSpecification &, V &); -template void Walk(format::FormatSpecification &, M &); -template void Walk(const format::IntrinsicTypeDataEditDesc &, V &); -template void Walk(format::IntrinsicTypeDataEditDesc &, M &); - -// Traversal of needed STL template classes (optional, list, tuple, variant) -// For most lists, just traverse the elements; but when a list constitutes -// a Block (i.e., std::list), also invoke the -// visitor/mutator on the list itself. -template void Walk(const std::list &x, V &visitor) { - for (const auto &elem : x) { - Walk(elem, visitor); +namespace detail { +// A number of the Walk functions below call other Walk functions. Define +// a dummy class, and put all of them in it to ensure that name lookup for +// Walk considers all overloads (not just those defined prior to the call +// to Walk). +struct ParseTreeVisitorLookupScope { + // Default case for visitation of non-class data members, strings, and + // any other non-decomposable values. + template + static std::enable_if_t || + std::is_same_v || std::is_same_v> + Walk(const A &x, V &visitor) { + if (visitor.Pre(x)) { + visitor.Post(x); + } } -} -template void Walk(std::list &x, M &mutator) { - for (auto &elem : x) { - Walk(elem, mutator); + template + static std::enable_if_t || + std::is_same_v || std::is_same_v> + Walk(A &x, M &mutator) { + if (mutator.Pre(x)) { + mutator.Post(x); + } } -} -template void Walk(const Block &x, V &visitor) { - if (visitor.Pre(x)) { + + // Traversal of needed STL template classes (optional, list, tuple, variant) + // For most lists, just traverse the elements; but when a list constitutes + // a Block (i.e., std::list), also invoke the + // visitor/mutator on the list itself. + template + static void Walk(const std::list &x, V &visitor) { for (const auto &elem : x) { Walk(elem, visitor); } - visitor.Post(x); } -} -template void Walk(Block &x, M &mutator) { - if (mutator.Pre(x)) { + template + static void Walk(std::list &x, M &mutator) { for (auto &elem : x) { Walk(elem, mutator); } - mutator.Post(x); } -} -template -void Walk(const std::optional &x, V &visitor) { - if (x) { - Walk(*x, visitor); + template static void Walk(const Block &x, V &visitor) { + if (visitor.Pre(x)) { + for (const auto &elem : x) { + Walk(elem, visitor); + } + visitor.Post(x); + } } -} -template void Walk(std::optional &x, M &mutator) { - if (x) { - Walk(*x, mutator); + template static void Walk(Block &x, M &mutator) { + if (mutator.Pre(x)) { + for (auto &elem : x) { + Walk(elem, mutator); + } + mutator.Post(x); + } } -} -template -void ForEachInTuple(const T &tuple, Func func) { - func(std::get(tuple)); - if constexpr (I + 1 < std::tuple_size_v) { - ForEachInTuple(tuple, func); + template + static void Walk(const std::optional &x, V &visitor) { + if (x) { + Walk(*x, visitor); + } } -} -template -void Walk(const std::tuple &x, V &visitor) { - if (sizeof...(A) > 0) { + template + static void Walk(std::optional &x, M &mutator) { + if (x) { + Walk(*x, mutator); + } + } + template + static void ForEachInTuple(const T &tuple, Func func) { + func(std::get(tuple)); + if constexpr (I + 1 < std::tuple_size_v) { + ForEachInTuple(tuple, func); + } + } + template + static void Walk(const std::tuple &x, V &visitor) { + if (sizeof...(A) > 0) { + if (visitor.Pre(x)) { + ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); }); + visitor.Post(x); + } + } + } + template + static void ForEachInTuple(T &tuple, Func func) { + func(std::get(tuple)); + if constexpr (I + 1 < std::tuple_size_v) { + ForEachInTuple(tuple, func); + } + } + template + static void Walk(std::tuple &x, M &mutator) { + if (sizeof...(A) > 0) { + if (mutator.Pre(x)) { + ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); }); + mutator.Post(x); + } + } + } + template + static void Walk(const std::variant &x, V &visitor) { if (visitor.Pre(x)) { - ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); }); + common::visit([&](const auto &y) { Walk(y, visitor); }, x); visitor.Post(x); } } -} -template -void ForEachInTuple(T &tuple, Func func) { - func(std::get(tuple)); - if constexpr (I + 1 < std::tuple_size_v) { - ForEachInTuple(tuple, func); - } -} -template -void Walk(std::tuple &x, M &mutator) { - if (sizeof...(A) > 0) { + template + static void Walk(std::variant &x, M &mutator) { if (mutator.Pre(x)) { - ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); }); + common::visit([&](auto &y) { Walk(y, mutator); }, x); mutator.Post(x); } } -} -template -void Walk(const std::variant &x, V &visitor) { - if (visitor.Pre(x)) { - common::visit([&](const auto &y) { Walk(y, visitor); }, x); - visitor.Post(x); + template + static void Walk(const std::pair &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.first, visitor); + Walk(x.second, visitor); + } } -} -template -void Walk(std::variant &x, M &mutator) { - if (mutator.Pre(x)) { - common::visit([&](auto &y) { Walk(y, mutator); }, x); - mutator.Post(x); + template + static void Walk(std::pair &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.first, mutator); + Walk(x.second, mutator); + } } -} -template -void Walk(const std::pair &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.first, visitor); - Walk(x.second, visitor); + + // Trait-determined traversal of empty, tuple, union, wrapper, + // and constraint-checking classes. + template + static std::enable_if_t> Walk(const A &x, V &visitor) { + if (visitor.Pre(x)) { + visitor.Post(x); + } } -} -template -void Walk(std::pair &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.first, mutator); - Walk(x.second, mutator); + template + static std::enable_if_t> Walk(A &x, M &mutator) { + if (mutator.Pre(x)) { + mutator.Post(x); + } } -} -// Trait-determined traversal of empty, tuple, union, wrapper, -// and constraint-checking classes. -template -std::enable_if_t> Walk(const A &x, V &visitor) { - if (visitor.Pre(x)) { - visitor.Post(x); + template + static std::enable_if_t> Walk(const A &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.t, visitor); + visitor.Post(x); + } } -} -template -std::enable_if_t> Walk(A &x, M &mutator) { - if (mutator.Pre(x)) { - mutator.Post(x); + template + static std::enable_if_t> Walk(A &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.t, mutator); + mutator.Post(x); + } } -} -template -std::enable_if_t> Walk(const A &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.t, visitor); - visitor.Post(x); + template + static std::enable_if_t> Walk(const A &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.u, visitor); + visitor.Post(x); + } } -} -template -std::enable_if_t> Walk(A &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.t, mutator); - mutator.Post(x); + template + static std::enable_if_t> Walk(A &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.u, mutator); + mutator.Post(x); + } } -} -template -std::enable_if_t> Walk(const A &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.u, visitor); - visitor.Post(x); + template + static std::enable_if_t> Walk(const A &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.v, visitor); + visitor.Post(x); + } } -} -template -std::enable_if_t> Walk(A &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.u, mutator); - mutator.Post(x); + template + static std::enable_if_t> Walk(A &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.v, mutator); + mutator.Post(x); + } } -} -template -std::enable_if_t> Walk(const A &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.v, visitor); - visitor.Post(x); + template + static std::enable_if_t> Walk(const A &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.thing, visitor); + visitor.Post(x); + } } -} -template -std::enable_if_t> Walk(A &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.v, mutator); - mutator.Post(x); + template + static std::enable_if_t> Walk(A &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.thing, mutator); + mutator.Post(x); + } } -} -template -std::enable_if_t> Walk(const A &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.thing, visitor); - visitor.Post(x); + template + static void Walk(const common::Indirection &x, V &visitor) { + Walk(x.value(), visitor); } -} -template -std::enable_if_t> Walk(A &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.thing, mutator); - mutator.Post(x); + template + static void Walk(common::Indirection &x, M &mutator) { + Walk(x.value(), mutator); } -} - -template -void Walk(const common::Indirection &x, V &visitor) { - Walk(x.value(), visitor); -} -template -void Walk(common::Indirection &x, M &mutator) { - Walk(x.value(), mutator); -} -template void Walk(const Statement &x, V &visitor) { - if (visitor.Pre(x)) { - // N.B. The label, if any, is not visited. - Walk(x.source, visitor); - Walk(x.statement, visitor); - visitor.Post(x); + template + static void Walk(const Statement &x, V &visitor) { + if (visitor.Pre(x)) { + // N.B. The label, if any, is not visited. + Walk(x.source, visitor); + Walk(x.statement, visitor); + visitor.Post(x); + } } -} -template void Walk(Statement &x, M &mutator) { - if (mutator.Pre(x)) { - // N.B. The label, if any, is not visited. - Walk(x.source, mutator); - Walk(x.statement, mutator); - mutator.Post(x); + template + static void Walk(Statement &x, M &mutator) { + if (mutator.Pre(x)) { + // N.B. The label, if any, is not visited. + Walk(x.source, mutator); + Walk(x.statement, mutator); + mutator.Post(x); + } } -} -template -void Walk(const UnlabeledStatement &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - Walk(x.statement, visitor); - visitor.Post(x); + template + static void Walk(const UnlabeledStatement &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + Walk(x.statement, visitor); + visitor.Post(x); + } } -} -template -void Walk(UnlabeledStatement &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - Walk(x.statement, mutator); - mutator.Post(x); + template + static void Walk(UnlabeledStatement &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + Walk(x.statement, mutator); + mutator.Post(x); + } } -} -template void Walk(const Name &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - visitor.Post(x); + template static void Walk(const Name &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + visitor.Post(x); + } } -} -template void Walk(Name &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - mutator.Post(x); + template static void Walk(Name &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + mutator.Post(x); + } } -} -template void Walk(const AcSpec &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.type, visitor); - Walk(x.values, visitor); - visitor.Post(x); + template static void Walk(const AcSpec &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.type, visitor); + Walk(x.values, visitor); + visitor.Post(x); + } } -} -template void Walk(AcSpec &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.type, mutator); - Walk(x.values, mutator); - mutator.Post(x); + template static void Walk(AcSpec &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.type, mutator); + Walk(x.values, mutator); + mutator.Post(x); + } } -} -template void Walk(const ArrayElement &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.base, visitor); - Walk(x.subscripts, visitor); - visitor.Post(x); + template static void Walk(const ArrayElement &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.base, visitor); + Walk(x.subscripts, visitor); + visitor.Post(x); + } } -} -template void Walk(ArrayElement &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.base, mutator); - Walk(x.subscripts, mutator); - mutator.Post(x); + template static void Walk(ArrayElement &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.base, mutator); + Walk(x.subscripts, mutator); + mutator.Post(x); + } } -} -template -void Walk(const CharSelector::LengthAndKind &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.length, visitor); - Walk(x.kind, visitor); - visitor.Post(x); + template + static void Walk(const CharSelector::LengthAndKind &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.length, visitor); + Walk(x.kind, visitor); + visitor.Post(x); + } } -} -template void Walk(CharSelector::LengthAndKind &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.length, mutator); - Walk(x.kind, mutator); - mutator.Post(x); + template + static void Walk(CharSelector::LengthAndKind &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.length, mutator); + Walk(x.kind, mutator); + mutator.Post(x); + } } -} -template void Walk(const CaseValueRange::Range &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.lower, visitor); - Walk(x.upper, visitor); - visitor.Post(x); + template + static void Walk(const CaseValueRange::Range &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.lower, visitor); + Walk(x.upper, visitor); + visitor.Post(x); + } } -} -template void Walk(CaseValueRange::Range &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.lower, mutator); - Walk(x.upper, mutator); - mutator.Post(x); + template static void Walk(CaseValueRange::Range &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.lower, mutator); + Walk(x.upper, mutator); + mutator.Post(x); + } } -} -template void Walk(const CoindexedNamedObject &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.base, visitor); - Walk(x.imageSelector, visitor); - visitor.Post(x); + template + static void Walk(const CoindexedNamedObject &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.base, visitor); + Walk(x.imageSelector, visitor); + visitor.Post(x); + } } -} -template void Walk(CoindexedNamedObject &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.base, mutator); - Walk(x.imageSelector, mutator); - mutator.Post(x); + template static void Walk(CoindexedNamedObject &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.base, mutator); + Walk(x.imageSelector, mutator); + mutator.Post(x); + } } -} -template -void Walk(const DeclarationTypeSpec::Class &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.derived, visitor); - visitor.Post(x); + template + static void Walk(const DeclarationTypeSpec::Class &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.derived, visitor); + visitor.Post(x); + } } -} -template void Walk(DeclarationTypeSpec::Class &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.derived, mutator); - mutator.Post(x); + template + static void Walk(DeclarationTypeSpec::Class &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.derived, mutator); + mutator.Post(x); + } } -} -template -void Walk(const DeclarationTypeSpec::Type &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.derived, visitor); - visitor.Post(x); + template + static void Walk(const DeclarationTypeSpec::Type &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.derived, visitor); + visitor.Post(x); + } } -} -template void Walk(DeclarationTypeSpec::Type &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.derived, mutator); - mutator.Post(x); + template + static void Walk(DeclarationTypeSpec::Type &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.derived, mutator); + mutator.Post(x); + } } -} -template void Walk(const ImportStmt &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.names, visitor); - visitor.Post(x); + template static void Walk(const ImportStmt &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.names, visitor); + visitor.Post(x); + } } -} -template void Walk(ImportStmt &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.names, mutator); - mutator.Post(x); + template static void Walk(ImportStmt &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.names, mutator); + mutator.Post(x); + } } -} -template -void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.selector, visitor); - visitor.Post(x); + template + static void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.selector, visitor); + visitor.Post(x); + } } -} -template void Walk(IntrinsicTypeSpec::Character &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.selector, mutator); - mutator.Post(x); + template + static void Walk(IntrinsicTypeSpec::Character &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.selector, mutator); + mutator.Post(x); + } } -} -template -void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - visitor.Post(x); + template + static void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + visitor.Post(x); + } } -} -template void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.kind, mutator); - mutator.Post(x); + template + static void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.kind, mutator); + mutator.Post(x); + } } -} -template -void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - visitor.Post(x); + template + static void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + visitor.Post(x); + } } -} -template void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.kind, mutator); - mutator.Post(x); + template + static void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.kind, mutator); + mutator.Post(x); + } } -} -template void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - visitor.Post(x); + template + static void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + visitor.Post(x); + } } -} -template void Walk(IntrinsicTypeSpec::Real &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.kind, mutator); - mutator.Post(x); + template + static void Walk(IntrinsicTypeSpec::Real &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.kind, mutator); + mutator.Post(x); + } } -} -template -void Walk(const LoopBounds &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.name, visitor); - Walk(x.lower, visitor); - Walk(x.upper, visitor); - Walk(x.step, visitor); - visitor.Post(x); + template + static void Walk(const LoopBounds &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.name, visitor); + Walk(x.lower, visitor); + Walk(x.upper, visitor); + Walk(x.step, visitor); + visitor.Post(x); + } } -} -template -void Walk(LoopBounds &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.name, mutator); - Walk(x.lower, mutator); - Walk(x.upper, mutator); - Walk(x.step, mutator); - mutator.Post(x); + template + static void Walk(LoopBounds &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.name, mutator); + Walk(x.lower, mutator); + Walk(x.upper, mutator); + Walk(x.step, mutator); + mutator.Post(x); + } } -} -template void Walk(const CommonStmt &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.blocks, visitor); - visitor.Post(x); + template static void Walk(const CommonStmt &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.blocks, visitor); + visitor.Post(x); + } } -} -template void Walk(CommonStmt &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.blocks, mutator); - mutator.Post(x); + template static void Walk(CommonStmt &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.blocks, mutator); + mutator.Post(x); + } } -} -// Expr traversal uses iteration rather than recursion to avoid -// blowing out the stack on very deep expression parse trees. -// It replaces implementations that looked like: -// template void Walk(const Expr &x, V visitor) { -// if (visitor.Pre(x)) { // Pre on the Expr -// Walk(x.source, visitor); -// // Pre on the operator, walk the operands, Post on operator -// Walk(x.u, visitor); -// visitor.Post(x); // Post on the Expr -// } -// } -template -static void IterativeWalk(A &start, V &visitor) { - struct ExprWorkList { - ExprWorkList(A &x) : expr(&x) {} - bool doPostExpr{false}, doPostOpr{false}; - A *expr; - }; - std::vector stack; - stack.emplace_back(start); - do { - A &expr{*stack.back().expr}; - if (stack.back().doPostOpr) { - stack.back().doPostOpr = false; - common::visit([&visitor](auto &y) { visitor.Post(y); }, expr.u); - } else if (stack.back().doPostExpr) { - visitor.Post(expr); - stack.pop_back(); - } else if (!visitor.Pre(expr)) { - stack.pop_back(); - } else { - stack.back().doPostExpr = true; - Walk(expr.source, visitor); - UNARY *unary{nullptr}; - BINARY *binary{nullptr}; - common::visit( - [&unary, &binary](auto &y) { - if constexpr (std::is_convertible_v) { - unary = &y; - } else if constexpr (std::is_convertible_v) { - binary = &y; - } - }, - expr.u); - if (!unary && !binary) { - Walk(expr.u, visitor); - } else if (common::visit( - [&visitor](auto &y) { return visitor.Pre(y); }, expr.u)) { - stack.back().doPostOpr = true; - if (unary) { - stack.emplace_back(unary->v.value()); - } else { - stack.emplace_back(std::get<1>(binary->t).value()); - stack.emplace_back(std::get<0>(binary->t).value()); + // Expr traversal uses iteration rather than recursion to avoid + // blowing out the stack on very deep expression parse trees. + // It replaces implementations that looked like: + // template static void Walk(const Expr &x, V visitor) { + // if (visitor.Pre(x)) { // Pre on the Expr + // Walk(x.source, visitor); + // // Pre on the operator, walk the operands, Post on operator + // Walk(x.u, visitor); + // visitor.Post(x); // Post on the Expr + // } + // } + template + static void IterativeWalk(A &start, V &visitor) { + struct ExprWorkList { + ExprWorkList(A &x) : expr(&x) {} + bool doPostExpr{false}, doPostOpr{false}; + A *expr; + }; + std::vector stack; + stack.emplace_back(start); + do { + A &expr{*stack.back().expr}; + if (stack.back().doPostOpr) { + stack.back().doPostOpr = false; + common::visit([&visitor](auto &y) { visitor.Post(y); }, expr.u); + } else if (stack.back().doPostExpr) { + visitor.Post(expr); + stack.pop_back(); + } else if (!visitor.Pre(expr)) { + stack.pop_back(); + } else { + stack.back().doPostExpr = true; + Walk(expr.source, visitor); + UNARY *unary{nullptr}; + BINARY *binary{nullptr}; + common::visit( + [&unary, &binary](auto &y) { + if constexpr (std::is_convertible_v) { + unary = &y; + } else if constexpr (std::is_convertible_v) { + binary = &y; + } + }, + expr.u); + if (!unary && !binary) { + Walk(expr.u, visitor); + } else if (common::visit([&visitor](auto &y) { return visitor.Pre(y); }, + expr.u)) { + stack.back().doPostOpr = true; + if (unary) { + stack.emplace_back(unary->v.value()); + } else { + stack.emplace_back(std::get<1>(binary->t).value()); + stack.emplace_back(std::get<0>(binary->t).value()); + } } } - } - } while (!stack.empty()); -} -template void Walk(const Expr &x, V &visitor) { - IterativeWalk(x, visitor); -} -template void Walk(Expr &x, M &mutator) { - IterativeWalk( - x, mutator); -} + } while (!stack.empty()); + } + template static void Walk(const Expr &x, V &visitor) { + IterativeWalk(x, visitor); + } + template static void Walk(Expr &x, M &mutator) { + IterativeWalk( + x, mutator); + } -template void Walk(const Designator &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - Walk(x.u, visitor); - visitor.Post(x); + template static void Walk(const Designator &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + Walk(x.u, visitor); + visitor.Post(x); + } } -} -template void Walk(Designator &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - Walk(x.u, mutator); - mutator.Post(x); + template static void Walk(Designator &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + Walk(x.u, mutator); + mutator.Post(x); + } } -} -template void Walk(const FunctionReference &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - Walk(x.v, visitor); - visitor.Post(x); + template + static void Walk(const FunctionReference &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + Walk(x.v, visitor); + visitor.Post(x); + } } -} -template void Walk(FunctionReference &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - Walk(x.v, mutator); - mutator.Post(x); + template static void Walk(FunctionReference &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + Walk(x.v, mutator); + mutator.Post(x); + } } -} -template void Walk(const CallStmt &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - Walk(x.call, visitor); - Walk(x.chevrons, visitor); - visitor.Post(x); + template static void Walk(const CallStmt &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + Walk(x.call, visitor); + Walk(x.chevrons, visitor); + visitor.Post(x); + } } -} -template void Walk(CallStmt &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - Walk(x.call, mutator); - Walk(x.chevrons, mutator); - mutator.Post(x); + template static void Walk(CallStmt &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + Walk(x.call, mutator); + Walk(x.chevrons, mutator); + mutator.Post(x); + } } -} -template void Walk(const PartRef &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.name, visitor); - Walk(x.subscripts, visitor); - Walk(x.imageSelector, visitor); - visitor.Post(x); + template static void Walk(const PartRef &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.name, visitor); + Walk(x.subscripts, visitor); + Walk(x.imageSelector, visitor); + visitor.Post(x); + } } -} -template void Walk(PartRef &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.name, mutator); - Walk(x.subscripts, mutator); - Walk(x.imageSelector, mutator); - mutator.Post(x); + template static void Walk(PartRef &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.name, mutator); + Walk(x.subscripts, mutator); + Walk(x.imageSelector, mutator); + mutator.Post(x); + } } -} -template void Walk(const ReadStmt &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.iounit, visitor); - Walk(x.format, visitor); - Walk(x.controls, visitor); - Walk(x.items, visitor); - visitor.Post(x); + template static void Walk(const ReadStmt &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.iounit, visitor); + Walk(x.format, visitor); + Walk(x.controls, visitor); + Walk(x.items, visitor); + visitor.Post(x); + } } -} -template void Walk(ReadStmt &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.iounit, mutator); - Walk(x.format, mutator); - Walk(x.controls, mutator); - Walk(x.items, mutator); - mutator.Post(x); + template static void Walk(ReadStmt &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.iounit, mutator); + Walk(x.format, mutator); + Walk(x.controls, mutator); + Walk(x.items, mutator); + mutator.Post(x); + } } -} -template void Walk(const SignedIntLiteralConstant &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - Walk(x.t, visitor); - visitor.Post(x); + template + static void Walk(const SignedIntLiteralConstant &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + Walk(x.t, visitor); + visitor.Post(x); + } } -} -template void Walk(SignedIntLiteralConstant &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - Walk(x.t, mutator); - mutator.Post(x); + template + static void Walk(SignedIntLiteralConstant &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + Walk(x.t, mutator); + mutator.Post(x); + } } -} -template void Walk(const RealLiteralConstant &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.real, visitor); - Walk(x.kind, visitor); - visitor.Post(x); + template + static void Walk(const RealLiteralConstant &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.real, visitor); + Walk(x.kind, visitor); + visitor.Post(x); + } } -} -template void Walk(RealLiteralConstant &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.real, mutator); - Walk(x.kind, mutator); - mutator.Post(x); + template static void Walk(RealLiteralConstant &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.real, mutator); + Walk(x.kind, mutator); + mutator.Post(x); + } } -} -template -void Walk(const RealLiteralConstant::Real &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - visitor.Post(x); + template + static void Walk(const RealLiteralConstant::Real &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + visitor.Post(x); + } } -} -template void Walk(RealLiteralConstant::Real &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - mutator.Post(x); + template + static void Walk(RealLiteralConstant::Real &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + mutator.Post(x); + } } -} -template void Walk(const StructureComponent &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.base, visitor); - Walk(x.component, visitor); - visitor.Post(x); + template + static void Walk(const StructureComponent &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.base, visitor); + Walk(x.component, visitor); + visitor.Post(x); + } } -} -template void Walk(StructureComponent &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.base, mutator); - Walk(x.component, mutator); - mutator.Post(x); + template static void Walk(StructureComponent &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.base, mutator); + Walk(x.component, mutator); + mutator.Post(x); + } } -} -template void Walk(const Suffix &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.binding, visitor); - Walk(x.resultName, visitor); - visitor.Post(x); + template static void Walk(const Suffix &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.binding, visitor); + Walk(x.resultName, visitor); + visitor.Post(x); + } } -} -template void Walk(Suffix &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.binding, mutator); - Walk(x.resultName, mutator); - mutator.Post(x); + template static void Walk(Suffix &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.binding, mutator); + Walk(x.resultName, mutator); + mutator.Post(x); + } } -} -template -void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.interfaceName, visitor); - Walk(x.attributes, visitor); - Walk(x.bindingNames, visitor); - visitor.Post(x); + template + static void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.interfaceName, visitor); + Walk(x.attributes, visitor); + Walk(x.bindingNames, visitor); + visitor.Post(x); + } } -} -template -void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.interfaceName, mutator); - Walk(x.attributes, mutator); - Walk(x.bindingNames, mutator); - mutator.Post(x); + template + static void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.interfaceName, mutator); + Walk(x.attributes, mutator); + Walk(x.bindingNames, mutator); + mutator.Post(x); + } } -} -template -void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.attributes, visitor); - Walk(x.declarations, visitor); - visitor.Post(x); + template + static void Walk( + const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.attributes, visitor); + Walk(x.declarations, visitor); + visitor.Post(x); + } } -} -template -void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.attributes, mutator); - Walk(x.declarations, mutator); - mutator.Post(x); + template + static void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.attributes, mutator); + Walk(x.declarations, mutator); + mutator.Post(x); + } } -} -template void Walk(const UseStmt &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.nature, visitor); - Walk(x.moduleName, visitor); - Walk(x.u, visitor); - visitor.Post(x); + template static void Walk(const UseStmt &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.nature, visitor); + Walk(x.moduleName, visitor); + Walk(x.u, visitor); + visitor.Post(x); + } } -} -template void Walk(UseStmt &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.nature, mutator); - Walk(x.moduleName, mutator); - Walk(x.u, mutator); - mutator.Post(x); + template static void Walk(UseStmt &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.nature, mutator); + Walk(x.moduleName, mutator); + Walk(x.u, mutator); + mutator.Post(x); + } } -} -template void Walk(const WriteStmt &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.iounit, visitor); - Walk(x.format, visitor); - Walk(x.controls, visitor); - Walk(x.items, visitor); - visitor.Post(x); + template static void Walk(const WriteStmt &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.iounit, visitor); + Walk(x.format, visitor); + Walk(x.controls, visitor); + Walk(x.items, visitor); + visitor.Post(x); + } } -} -template void Walk(WriteStmt &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.iounit, mutator); - Walk(x.format, mutator); - Walk(x.controls, mutator); - Walk(x.items, mutator); - mutator.Post(x); + template static void Walk(WriteStmt &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.iounit, mutator); + Walk(x.format, mutator); + Walk(x.controls, mutator); + Walk(x.items, mutator); + mutator.Post(x); + } } -} -template void Walk(const format::ControlEditDesc &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - visitor.Post(x); + template + static void Walk(const format::ControlEditDesc &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + visitor.Post(x); + } } -} -template void Walk(format::ControlEditDesc &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.kind, mutator); - mutator.Post(x); + template + static void Walk(format::ControlEditDesc &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.kind, mutator); + mutator.Post(x); + } } -} -template -void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.type, visitor); - Walk(x.parameters, visitor); - visitor.Post(x); + template + static void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.type, visitor); + Walk(x.parameters, visitor); + visitor.Post(x); + } } -} -template -void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.type, mutator); - Walk(x.parameters, mutator); - mutator.Post(x); + template + static void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.type, mutator); + Walk(x.parameters, mutator); + mutator.Post(x); + } } -} -template void Walk(const format::FormatItem &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.repeatCount, visitor); - Walk(x.u, visitor); - visitor.Post(x); + template + static void Walk(const format::FormatItem &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.repeatCount, visitor); + Walk(x.u, visitor); + visitor.Post(x); + } } -} -template void Walk(format::FormatItem &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.repeatCount, mutator); - Walk(x.u, mutator); - mutator.Post(x); + template static void Walk(format::FormatItem &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.repeatCount, mutator); + Walk(x.u, mutator); + mutator.Post(x); + } } -} -template -void Walk(const format::FormatSpecification &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.items, visitor); - Walk(x.unlimitedItems, visitor); - visitor.Post(x); + template + static void Walk(const format::FormatSpecification &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.items, visitor); + Walk(x.unlimitedItems, visitor); + visitor.Post(x); + } } -} -template void Walk(format::FormatSpecification &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.items, mutator); - Walk(x.unlimitedItems, mutator); - mutator.Post(x); + template + static void Walk(format::FormatSpecification &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.items, mutator); + Walk(x.unlimitedItems, mutator); + mutator.Post(x); + } } -} -template -void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.kind, visitor); - Walk(x.width, visitor); - Walk(x.digits, visitor); - Walk(x.exponentWidth, visitor); - visitor.Post(x); + template + static void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.kind, visitor); + Walk(x.width, visitor); + Walk(x.digits, visitor); + Walk(x.exponentWidth, visitor); + visitor.Post(x); + } } -} -template -void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.kind, mutator); - Walk(x.width, mutator); - Walk(x.digits, mutator); - Walk(x.exponentWidth, mutator); - mutator.Post(x); + template + static void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.kind, mutator); + Walk(x.width, mutator); + Walk(x.digits, mutator); + Walk(x.exponentWidth, mutator); + mutator.Post(x); + } } -} -template void Walk(const CompilerDirective &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.source, visitor); - Walk(x.u, visitor); - visitor.Post(x); + template + static void Walk(const CompilerDirective &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.source, visitor); + Walk(x.u, visitor); + visitor.Post(x); + } } -} -template void Walk(CompilerDirective &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.source, mutator); - Walk(x.u, mutator); - mutator.Post(x); + template static void Walk(CompilerDirective &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.source, mutator); + Walk(x.u, mutator); + mutator.Post(x); + } } -} -template -void Walk(const CompilerDirective::Unrecognized &x, V &visitor) { - if (visitor.Pre(x)) { - visitor.Post(x); + template + static void Walk(const CompilerDirective::Unrecognized &x, V &visitor) { + if (visitor.Pre(x)) { + visitor.Post(x); + } } -} -template -void Walk(CompilerDirective::Unrecognized &x, M &mutator) { - if (mutator.Pre(x)) { - mutator.Post(x); + template + static void Walk(CompilerDirective::Unrecognized &x, M &mutator) { + if (mutator.Pre(x)) { + mutator.Post(x); + } } -} -template -void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.modifier, visitor); - Walk(x.names, visitor); - Walk(x.step, visitor); - visitor.Post(x); + template + static void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.modifier, visitor); + Walk(x.names, visitor); + Walk(x.step, visitor); + visitor.Post(x); + } } -} -template void Walk(OmpLinearClause::WithModifier &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.modifier, mutator); - Walk(x.names, mutator); - Walk(x.step, mutator); - mutator.Post(x); + template + static void Walk(OmpLinearClause::WithModifier &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.modifier, mutator); + Walk(x.names, mutator); + Walk(x.step, mutator); + mutator.Post(x); + } } -} -template -void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) { - if (visitor.Pre(x)) { - Walk(x.names, visitor); - Walk(x.step, visitor); - visitor.Post(x); + template + static void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) { + if (visitor.Pre(x)) { + Walk(x.names, visitor); + Walk(x.step, visitor); + visitor.Post(x); + } } -} -template -void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) { - if (mutator.Pre(x)) { - Walk(x.names, mutator); - Walk(x.step, mutator); - mutator.Post(x); + template + static void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) { + if (mutator.Pre(x)) { + Walk(x.names, mutator); + Walk(x.step, mutator); + mutator.Post(x); + } } +}; +} // namespace detail + +template void Walk(const A &x, V &visitor) { + detail::ParseTreeVisitorLookupScope::Walk(x, visitor); } + +template void Walk(A &x, M &mutator) { + detail::ParseTreeVisitorLookupScope::Walk(x, mutator); +} + } // namespace Fortran::parser #endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 5f5650304f99874816798ee62ef5f2190c3f4532..22b7f9acd1af524962c984ba77b7e213d111c03e 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -1783,8 +1783,8 @@ struct PartRef { BOILERPLATE(PartRef); PartRef(Name &&n, std::list &&ss, std::optional &&is) - : name{std::move(n)}, - subscripts(std::move(ss)), imageSelector{std::move(is)} {} + : name{std::move(n)}, subscripts(std::move(ss)), + imageSelector{std::move(is)} {} Name name; std::list subscripts; std::optional imageSelector; @@ -3440,13 +3440,33 @@ struct OmpObject { WRAPPER_CLASS(OmpObjectList, std::list); +inline namespace modifier { +// For uniformity, in all keyword modifiers the name of the type defined +// by ENUM_CLASS is "Value", e.g. +// struct Foo { +// ENUM_CLASS(Value, Keyword1, Keyword2); +// }; + +// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69] +// +// iterator-specifier -> +// [iterator-type] iterator-identifier +// = range-specification | // since 5.0 +// [iterator-type ::] iterator-identifier +// = range-specification // since 5.2 +struct OmpIteratorSpecifier { + TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier); + CharBlock source; + std::tuple t; +}; + // Ref: [4.5:169-170], [5.0:255-256], [5.1:288-289] // // dependence-type -> -// SINK | SOURCE | // since 4.5 -// IN | OUT | INOUT | // since 4.5, until 5.1 -// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1 -// INOUTSET // since 5.1, until 5.1 +// SINK | SOURCE | // since 4.5 +// IN | OUT | INOUT | // since 4.5, until 5.1 +// MUTEXINOUTSET | DEPOBJ | // since 5.0, until 5.1 +// INOUTSET // since 5.1, until 5.1 // // All of these, except SINK and SOURCE became task-dependence-type in 5.2. // @@ -3457,45 +3477,59 @@ WRAPPER_CLASS(OmpObjectList, std::list); // vector). This would accept the vector "i, j, k" (although interpreted // incorrectly), while flagging a syntax error for "i+1, j, k". struct OmpDependenceType { - ENUM_CLASS(Type, Sink, Source); - WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Type); + ENUM_CLASS(Value, Sink, Source); + WRAPPER_CLASS_BOILERPLATE(OmpDependenceType, Value); }; -// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321] +// Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69] // -// task-dependence-type -> // "dependence-type" in 5.1 and before -// IN | OUT | INOUT | // since 4.5 -// MUTEXINOUTSET | DEPOBJ | // since 5.0 -// INOUTSET // since 5.2 -struct OmpTaskDependenceType { - ENUM_CLASS(Type, In, Out, Inout, Inoutset, Mutexinoutset, Depobj) - WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Type); +// iterator-modifier -> +// ITERATOR(iterator-specifier [, ...]) // since 5.0 +struct OmpIterator { + WRAPPER_CLASS_BOILERPLATE(OmpIterator, std::list); }; -// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple -// iterator-modifier -> iterator-specifier-list -struct OmpIteratorSpecifier { - TUPLE_CLASS_BOILERPLATE(OmpIteratorSpecifier); - CharBlock source; - std::tuple t; +// Ref: [4.5:207-210], [5.0:290-293], [5.1:323-325], [5.2:117-120] +// +// linear-modifier -> +// REF | UVAL | VAL // since 4.5 +struct OmpLinearModifier { + ENUM_CLASS(Value, Ref, Uval, Val); + WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Value); }; -WRAPPER_CLASS(OmpIteratorModifier, std::list); - -// 2.15.3.6 reduction-identifier -> + | - | * | .AND. | .OR. | .EQV. | .NEQV. | -// MAX | MIN | IAND | IOR | IEOR -struct OmpReductionOperator { - UNION_CLASS_BOILERPLATE(OmpReductionOperator); +// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124] +// +// reduction-identifier -> +// base-language-identifier | // since 4.5 +// - | // since 4.5, until 5.2 +// + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5 +// MIN | MAX | IAND | IOR | IEOR // since 4.5 +// +struct OmpReductionIdentifier { + UNION_CLASS_BOILERPLATE(OmpReductionIdentifier); std::variant u; }; +// Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321] +// +// task-dependence-type -> // "dependence-type" in 5.1 and before +// IN | OUT | INOUT | // since 4.5 +// MUTEXINOUTSET | DEPOBJ | // since 5.0 +// INOUTSET // since 5.2 +struct OmpTaskDependenceType { + ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj) + WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value); +}; +} // namespace modifier + // --- Clauses // OMP 5.0 2.10.1 affinity([aff-modifier:] locator-list) // aff-modifier: interator-modifier struct OmpAffinityClause { TUPLE_CLASS_BOILERPLATE(OmpAffinityClause); - std::tuple, OmpObjectList> t; + std::tuple, OmpObjectList> t; }; // 2.8.1 aligned-clause -> ALIGNED (variable-name-list[ : scalar-constant]) @@ -3544,7 +3578,7 @@ struct OmpDefaultmapClause { TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause); ENUM_CLASS( ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default) - ENUM_CLASS(VariableCategory, Scalar, Aggregate, Allocatable, Pointer) + ENUM_CLASS(VariableCategory, All, Scalar, Aggregate, Allocatable, Pointer) std::tuple> t; }; @@ -3566,7 +3600,7 @@ WRAPPER_CLASS(OmpIterationVector, std::list); // OmpDoacrossClause), so that the context in TYPE_CONTEXT_PARSER can be set // separately for OmpDependClause and OmpDoacrossClause. struct OmpDoacross { - OmpDependenceType::Type GetDepType() const; + OmpDependenceType::Value GetDepType() const; WRAPPER_CLASS(Sink, OmpIterationVector); EMPTY_CLASS(Source); @@ -3586,10 +3620,9 @@ struct OmpDoacross { struct OmpDependClause { UNION_CLASS_BOILERPLATE(OmpDependClause); struct TaskDep { - OmpTaskDependenceType::Type GetTaskDepType() const; + OmpTaskDependenceType::Value GetTaskDepType() const; TUPLE_CLASS_BOILERPLATE(TaskDep); - std::tuple, OmpTaskDependenceType, - OmpObjectList> + std::tuple, OmpTaskDependenceType, OmpObjectList> t; }; std::variant u; @@ -3632,7 +3665,7 @@ struct OmpFromClause { // As in the case of MAP, modifiers are parsed as lists, even if they // are unique. These restrictions will be checked in semantic checks. std::tuple>, - std::optional>, OmpObjectList, + std::optional>, OmpObjectList, bool> // were the modifiers comma-separated? t; }; @@ -3661,7 +3694,7 @@ struct OmpDetachClause { // variable-name-list) struct OmpInReductionClause { TUPLE_CLASS_BOILERPLATE(OmpInReductionClause); - std::tuple t; + std::tuple t; }; // OMP 5.0 2.19.4.5 lastprivate-clause -> @@ -3673,12 +3706,6 @@ struct OmpLastprivateClause { std::tuple, OmpObjectList> t; }; -// 2.15.3.7 linear-modifier -> REF | VAL | UVAL -struct OmpLinearModifier { - ENUM_CLASS(Type, Ref, Val, Uval) - WRAPPER_CLASS_BOILERPLATE(OmpLinearModifier, Type); -}; - // 2.15.3.7 linear-clause -> LINEAR (linear-list[ : linear-step]) // linear-list -> list | linear-modifier(list) struct OmpLinearClause { @@ -3703,8 +3730,11 @@ struct OmpLinearClause { std::variant u; }; +WRAPPER_CLASS(OmpMapperIdentifier, std::optional); + // 2.15.5.1 map -> -// MAP ([[map-type-modifier-list [,]] [iterator-modifier [,]] map-type : ] +// MAP ([MAPPER(mapper-identifier)] [[map-type-modifier-list [,]] +// [iterator-modifier [,]] map-type : ] // variable-name-list) // map-type-modifier-list -> map-type-modifier [,] [...] // map-type-modifier -> ALWAYS | CLOSE | PRESENT | OMPX_HOLD @@ -3718,8 +3748,9 @@ struct OmpMapClause { // The checks for satisfying those constraints are deferred to semantics. // In OpenMP 5.2 the non-comma syntax has been deprecated: keep the // information about separator presence to emit a diagnostic if needed. - std::tuple>, - std::optional>, // unique + std::tuple>, + std::optional>, // unique std::optional>, // unique OmpObjectList, bool> // were the modifiers comma-separated? @@ -3749,7 +3780,7 @@ struct OmpProcBindClause { struct OmpReductionClause { TUPLE_CLASS_BOILERPLATE(OmpReductionClause); ENUM_CLASS(ReductionModifier, Inscan, Task, Default) - std::tuple, OmpReductionOperator, + std::tuple, OmpReductionIdentifier, OmpObjectList> t; }; @@ -3794,7 +3825,7 @@ struct OmpToClause { // As in the case of MAP, modifiers are parsed as lists, even if they // are unique. These restrictions will be checked in semantic checks. std::tuple>, - std::optional>, OmpObjectList, + std::optional>, OmpObjectList, bool> // were the modifiers comma-separated? t; }; @@ -3916,6 +3947,19 @@ struct OpenMPDeclareTargetConstruct { std::tuple t; }; +struct OmpDeclareMapperSpecifier { + TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier); + std::tuple, TypeSpec, Name> t; +}; + +// OMP v5.2: 5.8.8 +// declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses +struct OpenMPDeclareMapperConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct); + CharBlock source; + std::tuple t; +}; + // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list // : combiner) [initializer-clause] struct OmpReductionCombiner { @@ -3929,7 +3973,7 @@ WRAPPER_CLASS(OmpReductionInitializerClause, Expr); struct OpenMPDeclareReductionConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct); CharBlock source; - std::tuple, + std::tuple, OmpReductionCombiner, std::optional> t; }; @@ -3966,9 +4010,10 @@ struct OpenMPDeclarativeAllocate { struct OpenMPDeclarativeConstruct { UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); CharBlock source; - std::variant + std::variant u; }; @@ -4527,12 +4572,17 @@ struct CUFReduction { struct CUFKernelDoConstruct { TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct); WRAPPER_CLASS(StarOrExpr, std::optional); + struct LaunchConfiguration { + TUPLE_CLASS_BOILERPLATE(LaunchConfiguration); + std::tuple, std::list, + std::optional> + t; + }; struct Directive { TUPLE_CLASS_BOILERPLATE(Directive); CharBlock source; - std::tuple, std::list, - std::list, std::optional, - std::list> + std::tuple, + std::optional, std::list> t; }; std::tuple> t; diff --git a/flang/include/flang/Runtime/CUDA/memory.h b/flang/include/flang/Runtime/CUDA/memory.h index 713bdf536aaf90f1eeccb16c8a0f3eb96156dc05..2bb083b0dd75cbf54be29afb6987e87cb837fd3b 100644 --- a/flang/include/flang/Runtime/CUDA/memory.h +++ b/flang/include/flang/Runtime/CUDA/memory.h @@ -44,6 +44,10 @@ void RTDECL(CUFDataTransferPtrDesc)(void *dst, Descriptor *src, void RTDECL(CUFDataTransferDescDesc)(Descriptor *dst, Descriptor *src, unsigned mode, const char *sourceFile = nullptr, int sourceLine = 0); +/// Data transfer from a scalar descriptor to a descriptor. +void RTDECL(CUFDataTransferCstDesc)(Descriptor *dst, Descriptor *src, + unsigned mode, const char *sourceFile = nullptr, int sourceLine = 0); + /// Data transfer from a descriptor to a descriptor. void RTDECL(CUFDataTransferDescDescNoRealloc)(Descriptor *dst, Descriptor *src, unsigned mode, const char *sourceFile = nullptr, int sourceLine = 0); diff --git a/flang/include/flang/Runtime/assign.h b/flang/include/flang/Runtime/assign.h index 0c1cd6fa207e7efaab615cab6c4493a7d93325fe..bc80997a1bec23e37bb06a20b3f5dea52bc01e8f 100644 --- a/flang/include/flang/Runtime/assign.h +++ b/flang/include/flang/Runtime/assign.h @@ -41,13 +41,7 @@ enum AssignFlags { DeallocateLHS = 1 << 6 }; -using MemmoveFct = void *(*)(void *, const void *, std::size_t); - #ifdef RT_DEVICE_COMPILATION -static RT_API_ATTRS void *MemmoveWrapper( - void *dest, const void *src, std::size_t count) { - return Fortran::runtime::memmove(dest, src, count); -} RT_API_ATTRS void Assign(Descriptor &to, const Descriptor &from, Terminator &terminator, int flags, MemmoveFct memmoveFct = &MemmoveWrapper); #else diff --git a/flang/include/flang/Runtime/freestanding-tools.h b/flang/include/flang/Runtime/freestanding-tools.h index 2e558c464f77188acdff1d39506371c72467abad..2e3feec1c47a9fc2a5ec4afa988d93942c976e47 100644 --- a/flang/include/flang/Runtime/freestanding-tools.h +++ b/flang/include/flang/Runtime/freestanding-tools.h @@ -109,6 +109,15 @@ static inline RT_API_ATTRS void *memmove( using std::memmove; #endif // !STD_MEMMOVE_UNSUPPORTED +using MemmoveFct = void *(*)(void *, const void *, std::size_t); + +#ifdef RT_DEVICE_COMPILATION +static RT_API_ATTRS void *MemmoveWrapper( + void *dest, const void *src, std::size_t count) { + return Fortran::runtime::memmove(dest, src, count); +} +#endif + #if STD_STRLEN_UNSUPPORTED // Provides alternative implementation for std::strlen(), if // it is not supported. diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h index 5e51c5c7de0e82b3e55706cc5327667c314a7705..7cdca1214e74987dd31aa1a3d46e8578b2a6ab96 100644 --- a/flang/include/flang/Semantics/openmp-directive-sets.h +++ b/flang/include/flang/Semantics/openmp-directive-sets.h @@ -290,6 +290,12 @@ static const OmpDirectiveSet workShareSet{ } | allDoSet, }; +//===----------------------------------------------------------------------===// +// Directive sets for parent directives that do allow/not allow a construct +//===----------------------------------------------------------------------===// + +static const OmpDirectiveSet scanParentAllowedSet{allDoSet | allSimdSet}; + //===----------------------------------------------------------------------===// // Directive sets for allowed/not allowed nested directives //===----------------------------------------------------------------------===// diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h new file mode 100644 index 0000000000000000000000000000000000000000..65d28f71fbc72676627f33da47a9ff8d635f6ad5 --- /dev/null +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -0,0 +1,391 @@ +//===-- flang/lib/Semantics/openmp-modifiers.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 +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_ +#define FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_ + +#include "flang/Common/enum-set.h" +#include "flang/Parser/parse-tree.h" +#include "flang/Semantics/semantics.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Frontend/OpenMP/OMP.h" + +#include +#include +#include +#include + +namespace Fortran::semantics { + +// Ref: [5.2:58] +// +// Syntactic properties for Clauses, Arguments and Modifiers +// +// Inverse properties: +// not Required -> Optional +// not Unique -> Repeatable +// not Exclusive -> Compatible +// not Ultimate -> Free +// +// Clause defaults: Optional, Repeatable, Compatible, Free +// Argument defaults: Required, Unique, Compatible, Free +// Modifier defaults: Optional, Unique, Compatible, Free +// +// --- +// Each modifier is used as either pre-modifier (i.e. modifier: item), +// or post-modifier (i.e. item: modifier). The default is pre-. +// Add an additional property that reflects the type of modifier. + +ENUM_CLASS(OmpProperty, Required, Unique, Exclusive, Ultimate, Post) +using OmpProperties = common::EnumSet; +using OmpClauses = + common::EnumSet; + +struct OmpModifierDescriptor { + // Modifier name for use in diagnostic messages. + const OmpProperties &props(unsigned version) const; + const OmpClauses &clauses(unsigned version) const; + + const llvm::StringRef name; + // Version-dependent properties of the modifier. + const std::map props_; + // Version-dependent set of clauses to which the modifier can apply. + const std::map clauses_; +}; + +template const OmpModifierDescriptor &OmpGetDescriptor(); + +template <> +const OmpModifierDescriptor &OmpGetDescriptor(); +template <> +const OmpModifierDescriptor &OmpGetDescriptor(); +template <> +const OmpModifierDescriptor &OmpGetDescriptor(); +template <> +const OmpModifierDescriptor &OmpGetDescriptor(); +template <> +const OmpModifierDescriptor &OmpGetDescriptor(); + +// Explanation of terminology: +// +// A typical clause with modifier[s] looks like this (with parts that are +// not relevant here removed): +// struct OmpSomeClause { +// struct Modifier { +// using Variant = std::variant; +// Variant u; +// }; +// std::tuple>, ...> t; +// }; +// +// The Speficic1, etc. refer to parser classes that represent modifiers, +// e.g. OmpIterator or OmpTaskDependenceType. The Variant type contains +// all modifiers that are allowed for a given clause. The Modifier class +// is there to wrap the variant into the form that the parse tree visitor +// expects, i.e. with traits, member "u", etc. +// +// To avoid ambiguities with the word "modifier" (e.g. is it "any modifier", +// or "this specific modifier"?), the following code uses different terms: +// +// - UnionTy: refers to the nested "Modifier" class, i.e. +// "OmpSomeClause::Modifier" in the example above. +// - SpecificTy: refers to any of the alternatives, i.e. "Specific1" or +// "Specific2". + +template +const OmpModifierDescriptor &OmpGetDescriptor(const UnionTy &modifier) { + return common::visit( + [](auto &&m) -> decltype(auto) { + using SpecificTy = llvm::remove_cvref_t; + return OmpGetDescriptor(); + }, + modifier.u); +} + +/// Return the optional list of modifiers for a given `Omp[...]Clause`. +/// Specifically, the parameter type `ClauseTy` is the class that OmpClause::v +/// holds. +template +const std::optional> &OmpGetModifiers( + const ClauseTy &clause) { + using UnionTy = typename ClauseTy::Modifier; + return std::get>>(clause.t); +} + +namespace detail { +/// Finds the first entry in the iterator range that holds the `SpecificTy` +/// alternative, or the end iterator if it does not exist. +/// The `SpecificTy` should be provided, the `UnionTy` is expected to be +/// auto-deduced, e.g. +/// const std::optional> &modifiers = ... +/// ... = findInRange(modifiers->begin(), modifiers->end()); +template +typename std::list::const_iterator findInRange( + typename std::list::const_iterator begin, + typename std::list::const_iterator end) { + for (auto it{begin}; it != end; ++it) { + if (std::holds_alternative(it->u)) { + return it; + } + } + return end; +} +} // namespace detail + +/// Finds the entry in the list that holds the `SpecificTy` alternative, +/// and returns the pointer to that alternative. If such an entry does not +/// exist, it returns nullptr. +/// The list is assumed to contain at most one such item, with a check +/// whether the condition is met. +/// This function should only be called after the verification of modifier +/// properties has been performed, since it will assert if multiple items +/// are found. +template +const SpecificTy *OmpGetUniqueModifier( + const std::optional> &modifiers) { + const SpecificTy *found{nullptr}; + if (modifiers) { + auto end{modifiers->cend()}; + // typename std::list::iterator end{modifiers->end()}; + auto at{detail::findInRange(modifiers->cbegin(), end)}; + if (at != end) { + found = &std::get(at->u); +#ifndef NDEBUG + auto another{ + detail::findInRange(std::next(at), end)}; + assert(another == end && "repeated modifier"); +#endif + } + } + return found; +} + +namespace detail { +template constexpr const T *make_nullptr() { + return static_cast(nullptr); +} + +/// Helper function for verifying the Required property: +/// For a specific SpecificTy, if SpecificTy is has the Required property, +/// check if the list has an item that holds SpecificTy as an alternative. +/// If SpecificTy does not have the Required property, ignore it. +template +bool verifyIfRequired(const SpecificTy *, + const std::optional> &modifiers, + parser::CharBlock clauseSource, SemanticsContext &semaCtx) { + unsigned version{semaCtx.langOptions().OpenMPVersion}; + const OmpModifierDescriptor &desc{OmpGetDescriptor()}; + if (!desc.props(version).test(OmpProperty::Required)) { + // If the modifier is not required, there is nothing to do. + return true; + } + bool present{modifiers.has_value()}; + present = present && llvm::any_of(*modifiers, [](auto &&m) { + return std::holds_alternative(m.u); + }); + if (!present) { + semaCtx.Say( + clauseSource, "A %s modifier is required"_err_en_US, desc.name.str()); + } + return present; +} + +/// Helper function for verifying the Required property: +/// Visit all specific types in UnionTy, and verify the Required property +/// for each one of them. +template +bool verifyRequiredPack(const std::optional> &modifiers, + parser::CharBlock clauseSource, SemanticsContext &semaCtx, + std::integer_sequence) { + using VariantTy = typename UnionTy::Variant; + return (verifyIfRequired( + make_nullptr>(), + modifiers, clauseSource, semaCtx) && + ...); +} + +/// Verify the Required property for the given list. Return true if the +/// list is valid, or false otherwise. +template +bool verifyRequired(const std::optional> &modifiers, + parser::CharBlock clauseSource, SemanticsContext &semaCtx) { + using VariantTy = typename UnionTy::Variant; + return verifyRequiredPack(modifiers, clauseSource, semaCtx, + std::make_index_sequence>{}); +} + +/// Helper function to verify the Unique property. +/// If SpecificTy has the Unique property, and an item is found holding +/// it as the alternative, verify that none of the elements that follow +/// hold SpecificTy as the alternative. +template +bool verifyIfUnique(const SpecificTy *, + typename std::list::const_iterator specific, + typename std::list::const_iterator end, + SemanticsContext &semaCtx) { + // `specific` is the location of the modifier of type SpecificTy. + assert(specific != end && "`specific` must be a valid location"); + + unsigned version{semaCtx.langOptions().OpenMPVersion}; + const OmpModifierDescriptor &desc{OmpGetDescriptor()}; + // Ultimate implies Unique. + if (!desc.props(version).test(OmpProperty::Unique) && + !desc.props(version).test(OmpProperty::Ultimate)) { + return true; + } + if (std::next(specific) != end) { + auto next{ + detail::findInRange(std::next(specific), end)}; + if (next != end) { + semaCtx.Say(next->source, "A %s cannot occur multiple times"_err_en_US, + desc.name.str()); + } + } + return true; +} + +/// Verify the Unique property for the given list. Return true if the +/// list is valid, or false otherwise. +template +bool verifyUnique(const std::optional> &modifiers, + parser::CharBlock clauseSource, SemanticsContext &semaCtx) { + if (!modifiers) { + return true; + } + bool result{true}; + for (auto it{modifiers->cbegin()}, end{modifiers->cend()}; it != end; ++it) { + result = common::visit( + [&](auto &&m) { + return verifyIfUnique(&m, it, end, semaCtx); + }, + it->u) && + result; + } + return result; +} + +/// Verify the Ultimate property for the given list. Return true if the +/// list is valid, or false otherwise. +template +bool verifyUltimate(const std::optional> &modifiers, + parser::CharBlock clauseSource, SemanticsContext &semaCtx) { + if (!modifiers || modifiers->size() <= 1) { + return true; + } + unsigned version{semaCtx.langOptions().OpenMPVersion}; + bool result{true}; + auto first{modifiers->cbegin()}; + auto last{std::prev(modifiers->cend())}; + + // Any item that has the Ultimate property has to be either at the back + // or at the front of the list (depending on whether it's a pre- or a post- + // modifier). + // Walk over the list, and if a given item has the Ultimate property but is + // not at the right position, mark it as an error. + for (auto it{first}, end{modifiers->cend()}; it != end; ++it) { + result = + common::visit( + [&](auto &&m) { + using SpecificTy = llvm::remove_cvref_t; + const OmpModifierDescriptor &desc{OmpGetDescriptor()}; + auto &props{desc.props(version)}; + + if (props.test(OmpProperty::Ultimate)) { + bool isPre = !props.test(OmpProperty::Post); + if (it == (isPre ? last : first)) { + // Skip, since this is the correct place for this modifier. + return true; + } + llvm::StringRef where{isPre ? "last" : "first"}; + semaCtx.Say(it->source, + "The %s should be the %s modifier"_err_en_US, + desc.name.str(), where.str()); + return false; + } + return true; + }, + it->u) && + result; + } + return result; +} + +/// Verify the Exclusive property for the given list. Return true if the +/// list is valid, or false otherwise. +template +bool verifyExclusive(const std::optional> &modifiers, + parser::CharBlock clauseSource, SemanticsContext &semaCtx) { + if (!modifiers || modifiers->size() <= 1) { + return true; + } + unsigned version{semaCtx.langOptions().OpenMPVersion}; + const UnionTy &front{modifiers->front()}; + const OmpModifierDescriptor &frontDesc{OmpGetDescriptor(front)}; + + auto second{std::next(modifiers->cbegin())}; + auto end{modifiers->end()}; + + auto emitErrorMessage{[&](const UnionTy &excl, const UnionTy &other) { + const OmpModifierDescriptor &descExcl{OmpGetDescriptor(excl)}; + const OmpModifierDescriptor &descOther{OmpGetDescriptor(other)}; + parser::MessageFormattedText txt( + "An exclusive %s cannot be specified together with a modifier of a different type"_err_en_US, + descExcl.name.str()); + parser::Message message(excl.source, txt); + message.Attach( + other.source, "%s provided here"_en_US, descOther.name.str()); + semaCtx.Say(std::move(message)); + }}; + + if (frontDesc.props(version).test(OmpProperty::Exclusive)) { + // If the first item has the Exclusive property, then check if there is + // another item in the rest of the list with a different SpecificTy as + // the alternative, and mark it as an error. This allows multiple Exclusive + // items to coexist as long as they hold the same SpecificTy. + bool result{true}; + size_t frontIndex{front.u.index()}; + for (auto it{second}; it != end; ++it) { + if (it->u.index() != frontIndex) { + emitErrorMessage(front, *it); + result = false; + break; + } + } + return result; + } else { + // If the first item does not have the Exclusive property, then check + // if there is an item in the rest of the list that is Exclusive, and + // mark it as an error if so. + bool result{true}; + for (auto it{second}; it != end; ++it) { + const OmpModifierDescriptor &desc{OmpGetDescriptor(*it)}; + if (desc.props(version).test(OmpProperty::Exclusive)) { + emitErrorMessage(*it, front); + result = false; + break; + } + } + return result; + } +} +} // namespace detail + +template +bool OmpVerifyModifiers(const ClauseTy &clause, parser::CharBlock clauseSource, + SemanticsContext &semaCtx) { + auto &modifiers{OmpGetModifiers(clause)}; + bool result{detail::verifyRequired(modifiers, clauseSource, semaCtx)}; + result = detail::verifyUnique(modifiers, clauseSource, semaCtx) && result; + result = detail::verifyUltimate(modifiers, clauseSource, semaCtx) && result; + result = detail::verifyExclusive(modifiers, clauseSource, semaCtx) && result; + return result; +} +} // namespace Fortran::semantics + +#endif // FORTRAN_SEMANTICS_OPENMP_MODIFIERS_H_ diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index b9512f33eaacd5485a2ab8c8d5430965e0812dca..2f97efddf7f7baf5daa105fad2d2a6f82d43b8d1 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -755,7 +755,8 @@ public: OmpDeclarativeAllocateDirective, OmpExecutableAllocateDirective, OmpDeclareSimd, OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock, OmpIfSpecified, OmpNone, OmpPreDetermined, - OmpImplicit, OmpDependObject); + OmpImplicit, OmpDependObject, OmpInclusiveScan, OmpExclusiveScan, + OmpInScanReduction); using Flags = common::EnumSet; const Scope &owner() const { return *owner_; } diff --git a/flang/include/flang/Tools/CrossToolHelpers.h b/flang/include/flang/Tools/CrossToolHelpers.h index df4b21ada058fe3694b1c465861a306da0067d12..d936b739e581573b80d997060f5a634266f619c4 100644 --- a/flang/include/flang/Tools/CrossToolHelpers.h +++ b/flang/include/flang/Tools/CrossToolHelpers.h @@ -123,6 +123,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks { false; ///< Set no-signed-zeros-fp-math attribute for functions. bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions. bool NSWOnLoopVarInc = false; ///< Add nsw flag to loop variable increments. + bool EnableOpenMP = false; ///< Enable OpenMP lowering. }; struct OffloadModuleOpts { diff --git a/flang/lib/Common/Fortran-features.cpp b/flang/lib/Common/Fortran-features.cpp index fff796e42552a52eb49d315dd482755f77a090c0..f47a4f17a6ba48dd3479fe82fe4cf7229c3da18b 100644 --- a/flang/lib/Common/Fortran-features.cpp +++ b/flang/lib/Common/Fortran-features.cpp @@ -30,6 +30,8 @@ LanguageFeatureControl::LanguageFeatureControl() { disable_.set(LanguageFeature::LogicalAbbreviations); disable_.set(LanguageFeature::XOROperator); disable_.set(LanguageFeature::OldStyleParameter); + // Possibly an accidental "feature" of nvfortran. + disable_.set(LanguageFeature::AssumedRankPassedToNonAssumedRank); // These warnings are enabled by default, but only because they used // to be unconditional. TODO: prune this list warnLanguage_.set(LanguageFeature::ExponentMatchingKindParam); diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp index 78cc63d0fde4018ed2eccd86af12bb0eeaaa5f2f..324d6b8dde73b8f48fda5197f37320c6d53393d3 100644 --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -731,11 +731,16 @@ static std::optional CharacterizeProcedure( return std::optional{}; } }, - [&](const semantics::EntityDetails &) { + [&](const semantics::EntityDetails &x) { CheckForNested(symbol); return std::optional{}; }, [&](const semantics::SubprogramNameDetails &) { + if (const semantics::Symbol * + ancestor{FindAncestorModuleProcedure(&symbol)}) { + return CharacterizeProcedure( + *ancestor, context, seenProcs, emitError); + } CheckForNested(symbol); return std::optional{}; }, diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 38794a2d8aacc70df9fa86889ad4f533692ed8cd..998378c44cdf4197221f234279ccc5932a9b8e3d 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -908,7 +908,58 @@ public: Result operator()(const ComplexPart &x) const { return x.complex().Rank() == 0; } - Result operator()(const Substring &) const { return std::nullopt; } + Result operator()(const Substring &x) const { + if (x.Rank() == 0) { + return true; // scalar substring always contiguous + } + // Substrings with rank must have DataRefs as their parents + const DataRef &parentDataRef{DEREF(x.GetParentIf())}; + std::optional len; + if (auto lenExpr{parentDataRef.LEN()}) { + len = ToInt64(Fold(context_, std::move(*lenExpr))); + if (len) { + if (*len <= 0) { + return true; // empty substrings + } else if (*len == 1) { + // Substrings can't be incomplete; is base array contiguous? + return (*this)(parentDataRef); + } + } + } + std::optional upper; + bool upperIsLen{false}; + if (auto upperExpr{x.upper()}) { + upper = ToInt64(Fold(context_, common::Clone(*upperExpr))); + if (upper) { + if (*upper < 1) { + return true; // substring(n:0) empty + } + upperIsLen = len && *upper >= *len; + } else if (const auto *inquiry{ + UnwrapConvertedExpr(*upperExpr)}; + inquiry && inquiry->field() == DescriptorInquiry::Field::Len) { + upperIsLen = + &parentDataRef.GetLastSymbol() == &inquiry->base().GetLastSymbol(); + } + } else { + upperIsLen = true; // substring(n:) + } + if (auto lower{ToInt64(Fold(context_, x.lower()))}) { + if (*lower == 1 && upperIsLen) { + // known complete substring; is base contiguous? + return (*this)(parentDataRef); + } else if (upper) { + if (*upper < *lower) { + return true; // empty substring(3:2) + } else if (*lower > 1) { + return false; // known incomplete substring + } else if (len && *upper < *len) { + return false; // known incomplete substring + } + } + } + return std::nullopt; // contiguity not known + } Result operator()(const ProcedureRef &x) const { if (auto chars{characteristics::Procedure::Characterize( diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index 594a614a5f2e76a5ad97fa24c06529537b6f8306..0ad09d76a6555d889003f56e22b791dd15d6d28b 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -873,7 +873,7 @@ Expr> FoldIntrinsicFunction( } else { DIE("first argument must be CHARACTER"); } - } else if (name == "int") { + } else if (name == "int" || name == "int2" || name == "int8") { if (auto *expr{UnwrapExpr>(args[0])}) { return common::visit( [&](auto &&x) -> Expr { diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index bb439a6bb3a746b3918555520765535315ccd265..c1b270f518c0e0a6a22d7468477194c34f6fc730 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -15,6 +15,7 @@ #include "fold-implementation.h" #include "host.h" #include "flang/Common/erfc-scaled.h" +#include "flang/Common/idioms.h" #include "flang/Common/static-multimap-view.h" #include "flang/Evaluate/expression.h" #include @@ -277,6 +278,76 @@ static std::complex StdPowF2B( return std::pow(x, y); } +#ifdef _AIX +#ifdef __clang_major__ +#pragma clang diagnostic ignored "-Wc99-extensions" +#endif + +extern "C" { +float _Complex cacosf(float _Complex); +double _Complex cacos(double _Complex); +float _Complex csqrtf(float _Complex); +double _Complex csqrt(double _Complex); +} + +enum CRI { Real, Imag }; +template static TR &reIm(TA &x, CRI n) { + return reinterpret_cast(x)[n]; +} +template static TR CppToC(const std::complex &x) { + TR r; + reIm(r, CRI::Real) = x.real(); + reIm(r, CRI::Imag) = x.imag(); + return r; +} +template static std::complex CToCpp(const TA &x) { + TA &z{const_cast(x)}; + return std::complex(reIm(z, CRI::Real), reIm(z, CRI::Imag)); +} +#endif + +template +static std::complex CSqrt(const std::complex &x) { + std::complex res; +#ifdef _AIX + // On AIX, the implementation of csqrt[f] and std::sqrt is different, + // use csqrt[f] in folding. + if constexpr (std::is_same_v) { + float _Complex r{csqrtf(CppToC(x))}; + res = CToCpp(r); + } else if constexpr (std::is_same_v) { + double _Complex r{csqrt(CppToC(x))}; + res = CToCpp(r); + } else { + DIE("bad complex component type"); + } +#else + res = std::sqrt(x); +#endif + return res; +} + +template +static std::complex CAcos(const std::complex &x) { + std::complex res; +#ifdef _AIX + // On AIX, the implementation of cacos[f] and std::acos is different, + // use cacos[f] in folding. + if constexpr (std::is_same_v) { + float _Complex r{cacosf(CppToC(x))}; + res = CToCpp(r); + } else if constexpr (std::is_same_v) { + double _Complex r{cacos(CppToC(x))}; + res = CToCpp(r); + } else { + DIE("bad complex component type"); + } +#else + res = std::acos(x); +#endif + return res; +} + template struct HostRuntimeLibrary, LibraryVersion::Libm> { using F = FuncPointer, const std::complex &>; @@ -287,7 +358,7 @@ struct HostRuntimeLibrary, LibraryVersion::Libm> { using F2B = FuncPointer, const std::complex &, const HostT &>; static constexpr HostRuntimeFunction table[]{ - FolderFactory::Create("acos"), + FolderFactory::Create("acos"), FolderFactory::Create("acosh"), FolderFactory::Create("asin"), FolderFactory::Create("asinh"), @@ -302,7 +373,7 @@ struct HostRuntimeLibrary, LibraryVersion::Libm> { FolderFactory::Create("pow"), FolderFactory::Create("sin"), FolderFactory::Create("sinh"), - FolderFactory::Create("sqrt"), + FolderFactory::Create("sqrt"), FolderFactory::Create("tan"), FolderFactory::Create("tanh"), }; diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index aa44967817722e37766c5573eb9828ff3f1ba598..1e27c0ae4216c5ea06ff0304d755e5bb32dc784e 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -168,8 +168,6 @@ static constexpr TypePattern SameCharNoLen{CharType, KindCode::sameKind}; static constexpr TypePattern SameLogical{LogicalType, KindCode::same}; static constexpr TypePattern SameRelatable{RelatableType, KindCode::same}; static constexpr TypePattern SameIntrinsic{IntrinsicType, KindCode::same}; -static constexpr TypePattern SameDerivedType{ - CategorySet{TypeCategory::Derived}, KindCode::same}; static constexpr TypePattern SameType{AnyType, KindCode::same}; // Match some kind of some INTEGER or REAL type(s); when argument types @@ -438,6 +436,12 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"shift", AnyInt}}, SameInt}, {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt}, + {"eoshift", + {{"array", SameType, Rank::array}, + {"shift", AnyInt, Rank::dimRemovedOrScalar}, + // BOUNDARY= is not optional for non-intrinsic types + {"boundary", SameType, Rank::dimRemovedOrScalar}, OptionalDIM}, + SameType, Rank::conformable, IntrinsicClass::transformationalFunction}, {"eoshift", {{"array", SameIntrinsic, Rank::array}, {"shift", AnyInt, Rank::dimRemovedOrScalar}, @@ -446,14 +450,6 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ OptionalDIM}, SameIntrinsic, Rank::conformable, IntrinsicClass::transformationalFunction}, - {"eoshift", - {{"array", SameDerivedType, Rank::array}, - {"shift", AnyInt, Rank::dimRemovedOrScalar}, - // BOUNDARY= is not optional for derived types - {"boundary", SameDerivedType, Rank::dimRemovedOrScalar}, - OptionalDIM}, - SameDerivedType, Rank::conformable, - IntrinsicClass::transformationalFunction}, {"epsilon", {{"x", SameReal, Rank::anyOrAssumedRank, Optionality::required, common::Intent::In, {ArgFlag::canBeMoldNull}}}, @@ -572,6 +568,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ DefaultingKIND}, KINDInt}, {"int", {{"a", AnyNumeric, Rank::elementalOrBOZ}, DefaultingKIND}, KINDInt}, + {"int2", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, + TypePattern{IntType, KindCode::exactKind, 2}}, + {"int8", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, + TypePattern{IntType, KindCode::exactKind, 8}}, {"int_ptr_kind", {}, DefaultInt, Rank::scalar}, {"ior", {{"i", OperandInt}, {"j", OperandInt, Rank::elementalOrBOZ}}, OperandInt}, @@ -1176,12 +1176,6 @@ static const SpecificIntrinsicInterface specificIntrinsicFunction[]{ // procedure pointer target. {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}}, DefaultInt}}, - {{"int2", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, - TypePattern{IntType, KindCode::exactKind, 2}}, - "int"}, - {{"int8", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, - TypePattern{IntType, KindCode::exactKind, 8}}, - "int"}, {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"}, {{"jiabs", {{"a", TypePattern{IntType, KindCode::exactKind, 4}}}, TypePattern{IntType, KindCode::exactKind, 4}}, @@ -1939,12 +1933,16 @@ std::optional IntrinsicInterface::Match( dimArg = j; argOk = true; break; - case KindCode::same: + case KindCode::same: { if (!sameArg) { sameArg = arg; } - argOk = type->IsTkLenCompatibleWith(sameArg->GetType().value()); - break; + // Check both ways so that a CLASS(*) actuals to + // MOVE_ALLOC and EOSHIFT both work. + auto sameType{sameArg->GetType().value()}; + argOk = sameType.IsTkLenCompatibleWith(*type) || + type->IsTkLenCompatibleWith(sameType); + } break; case KindCode::sameKind: if (!sameArg) { sameArg = arg; @@ -2849,15 +2847,16 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer( "FPTR= argument to C_F_POINTER() may not have a deferred type parameter"_err_en_US); } else if (type->category() == TypeCategory::Derived) { if (context.languageFeatures().ShouldWarn( - common::UsageWarning::Interoperability)) { - if (type->IsUnlimitedPolymorphic()) { - context.messages().Say(common::UsageWarning::Interoperability, at, - "FPTR= argument to C_F_POINTER() should not be unlimited polymorphic"_warn_en_US); - } else if (!type->GetDerivedTypeSpec().typeSymbol().attrs().test( - semantics::Attr::BIND_C)) { - context.messages().Say(common::UsageWarning::Interoperability, at, - "FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C)"_warn_en_US); - } + common::UsageWarning::Interoperability) && + type->IsUnlimitedPolymorphic()) { + context.messages().Say(common::UsageWarning::Interoperability, at, + "FPTR= argument to C_F_POINTER() should not be unlimited polymorphic"_warn_en_US); + } else if (!type->GetDerivedTypeSpec().typeSymbol().attrs().test( + semantics::Attr::BIND_C) && + context.languageFeatures().ShouldWarn( + common::UsageWarning::Portability)) { + context.messages().Say(common::UsageWarning::Portability, at, + "FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C)"_port_en_US); } } else if (!IsInteroperableIntrinsicType( *type, &context.languageFeatures()) diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index 4d98220a7065ca183cc415b7275af386cdab973f..15e3e9452894dec57428567f1390cee32f5291aa 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1990,4 +1990,37 @@ std::optional GetDummyArgumentNumber(const Symbol *symbol) { return std::nullopt; } +// Given a symbol that is a SubprogramNameDetails in a submodule, try to +// find its interface definition in its module or ancestor submodule. +const Symbol *FindAncestorModuleProcedure(const Symbol *symInSubmodule) { + if (symInSubmodule && symInSubmodule->owner().IsSubmodule()) { + if (const auto *nameDetails{ + symInSubmodule->detailsIf()}; + nameDetails && + nameDetails->kind() == semantics::SubprogramKind::Module) { + const Symbol *next{symInSubmodule->owner().symbol()}; + while (const Symbol * submodSym{next}) { + next = nullptr; + if (const auto *modDetails{ + submodSym->detailsIf()}; + modDetails && modDetails->isSubmodule() && modDetails->scope()) { + if (const semantics::Scope & parent{modDetails->scope()->parent()}; + parent.IsSubmodule() || parent.IsModule()) { + if (auto iter{parent.find(symInSubmodule->name())}; + iter != parent.end()) { + const Symbol &proc{iter->second->GetUltimate()}; + if (IsProcedure(proc)) { + return &proc; + } + } else if (parent.IsSubmodule()) { + next = parent.symbol(); + } + } + } + } + } + } + return nullptr; +} + } // namespace Fortran::semantics diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index f2e460fc53a67f40e027a75a39424dda56a0baa3..8c21fe18e67b4d8dc05b8a17d86e6a8071b79988 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -715,7 +715,11 @@ void CodeGenAction::lowerHLFIRToFIR() { pm.enableVerifier(/*verifyPasses=*/true); // Create the pass pipeline - fir::createHLFIRToFIRPassPipeline(pm, level); + fir::createHLFIRToFIRPassPipeline( + pm, + ci.getInvocation().getFrontendOpts().features.IsEnabled( + Fortran::common::LanguageFeature::OpenMP), + level); (void)mlir::applyPassManagerCLOptions(pm); if (!mlir::succeeded(pm.run(*mlirModule))) { @@ -828,6 +832,10 @@ void CodeGenAction::generateLLVMIR() { config.VScaleMax = vsr->second; } + if (ci.getInvocation().getFrontendOpts().features.IsEnabled( + Fortran::common::LanguageFeature::OpenMP)) + config.EnableOpenMP = true; + if (ci.getInvocation().getLoweringOpts().getNSWOnLoopVarInc()) config.NSWOnLoopVarInc = true; diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 0e3011e73902da0716111a9a327445d98a35f3c1..7f41742bf5e8b2fbbf14f9a072ca0881ce9d0fd8 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -1621,13 +1621,19 @@ private: // Termination of symbolically referenced execution units //===--------------------------------------------------------------------===// - /// END of program + /// Exit of a routine /// - /// Generate the cleanup block before the program exits - void genExitRoutine() { - - if (blockIsUnterminated()) - builder->create(toLocation()); + /// Generate the cleanup block before the routine exits + void genExitRoutine(bool earlyReturn, mlir::ValueRange retval = {}) { + if (blockIsUnterminated()) { + bridge.openAccCtx().finalizeAndKeep(); + bridge.fctCtx().finalizeAndKeep(); + builder->create(toLocation(), retval); + } + if (!earlyReturn) { + bridge.openAccCtx().pop(); + bridge.fctCtx().pop(); + } } /// END of procedure-like constructs @@ -1684,9 +1690,7 @@ private: resultRef = builder->createConvert(loc, resultRefType, resultRef); return builder->create(loc, resultRef); }); - bridge.openAccCtx().finalizeAndPop(); - bridge.fctCtx().finalizeAndPop(); - builder->create(loc, resultVal); + genExitRoutine(false, resultVal); } /// Get the return value of a call to \p symbol, which is a subroutine entry @@ -1712,13 +1716,9 @@ private: } else if (Fortran::semantics::HasAlternateReturns(symbol)) { mlir::Value retval = builder->create( toLocation(), getAltReturnResult(symbol)); - bridge.openAccCtx().finalizeAndPop(); - bridge.fctCtx().finalizeAndPop(); - builder->create(toLocation(), retval); + genExitRoutine(false, retval); } else { - bridge.openAccCtx().finalizeAndPop(); - bridge.fctCtx().finalizeAndPop(); - genExitRoutine(); + genExitRoutine(false); } } @@ -2862,14 +2862,11 @@ private: if (nestedLoops > 1) n = builder->getIntegerAttr(builder->getI64Type(), nestedLoops); - const std::list &grid = - std::get<1>(dir.t); - const std::list &block = - std::get<2>(dir.t); - const std::optional &stream = - std::get<3>(dir.t); + const auto &launchConfig = std::get>(dir.t); + const std::list &cufreds = - std::get<4>(dir.t); + std::get<2>(dir.t); llvm::SmallVector reduceOperands; llvm::SmallVector reduceAttrs; @@ -2913,35 +2910,45 @@ private: builder->createIntegerConstant(loc, builder->getI32Type(), 0); llvm::SmallVector gridValues; - if (!isOnlyStars(grid)) { - for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : - grid) { - if (expr.v) { - gridValues.push_back(fir::getBase( - genExprValue(*Fortran::semantics::GetExpr(*expr.v), stmtCtx))); - } else { - gridValues.push_back(zero); + llvm::SmallVector blockValues; + mlir::Value streamValue; + + if (launchConfig) { + const std::list &grid = + std::get<0>(launchConfig->t); + const std::list + &block = std::get<1>(launchConfig->t); + const std::optional &stream = + std::get<2>(launchConfig->t); + if (!isOnlyStars(grid)) { + for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : + grid) { + if (expr.v) { + gridValues.push_back(fir::getBase( + genExprValue(*Fortran::semantics::GetExpr(*expr.v), stmtCtx))); + } else { + gridValues.push_back(zero); + } } } - } - llvm::SmallVector blockValues; - if (!isOnlyStars(block)) { - for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : - block) { - if (expr.v) { - blockValues.push_back(fir::getBase( - genExprValue(*Fortran::semantics::GetExpr(*expr.v), stmtCtx))); - } else { - blockValues.push_back(zero); + if (!isOnlyStars(block)) { + for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : + block) { + if (expr.v) { + blockValues.push_back(fir::getBase( + genExprValue(*Fortran::semantics::GetExpr(*expr.v), stmtCtx))); + } else { + blockValues.push_back(zero); + } } } + + if (stream) + streamValue = builder->createConvert( + loc, builder->getI32Type(), + fir::getBase( + genExprValue(*Fortran::semantics::GetExpr(*stream), stmtCtx))); } - mlir::Value streamValue; - if (stream) - streamValue = builder->createConvert( - loc, builder->getI32Type(), - fir::getBase( - genExprValue(*Fortran::semantics::GetExpr(*stream), stmtCtx))); const auto &outerDoConstruct = std::get>(kernel.t); @@ -5011,8 +5018,7 @@ private: it->stmtCtx.finalizeAndKeep(); } if (funit->isMainProgram()) { - bridge.fctCtx().finalizeAndKeep(); - genExitRoutine(); + genExitRoutine(true); return; } mlir::Location loc = toLocation(); @@ -5471,9 +5477,7 @@ private: void endNewFunction(Fortran::lower::pft::FunctionLikeUnit &funit) { setCurrentPosition(Fortran::lower::pft::stmtSourceLoc(funit.endStmt)); if (funit.isMainProgram()) { - bridge.openAccCtx().finalizeAndPop(); - bridge.fctCtx().finalizeAndPop(); - genExitRoutine(); + genExitRoutine(false); } else { genFIRProcedureExit(funit, funit.getSubprogramSymbol()); } diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 7fc6b14f9c6606f1e00c08cc0c6e205a1e480e98..e20b90b2ff1bcb08bbbfb479e5957501000cdd02 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -1107,17 +1107,22 @@ private: }; if (obj.attrs.test(Attrs::Optional)) addMLIRAttr(fir::getOptionalAttrName()); - // Skipping obj.attrs.test(Attrs::Asynchronous), this does not impact the - // way the argument is passed given flang implement asynch IO synchronously. - // TODO: it would be safer to treat them as volatile because since Fortran - // 2018 asynchronous can also be used for C defined asynchronous user - // processes (see 18.10.4 Asynchronous communication). if (obj.attrs.test(Attrs::Contiguous)) addMLIRAttr(fir::getContiguousAttrName()); if (obj.attrs.test(Attrs::Value)) isValueAttr = true; // TODO: do we want an mlir::Attribute as well? - if (obj.attrs.test(Attrs::Volatile)) + if (obj.attrs.test(Attrs::Volatile)) { TODO(loc, "VOLATILE in procedure interface"); + addMLIRAttr(fir::getVolatileAttrName()); + } + // obj.attrs.test(Attrs::Asynchronous) does not impact the way the argument + // is passed given flang implement asynch IO synchronously. However, it's + // added to determine whether the argument is captured. + // TODO: it would be safer to treat them as volatile because since Fortran + // 2018 asynchronous can also be used for C defined asynchronous user + // processes (see 18.10.4 Asynchronous communication). + if (obj.attrs.test(Attrs::Asynchronous)) + addMLIRAttr(fir::getAsynchronousAttrName()); if (obj.attrs.test(Attrs::Target)) addMLIRAttr(fir::getTargetAttrName()); if (obj.cudaDataAttr) diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index 9f5b58590fb79e7875484be0ea593b641cf7d0b8..e84e7afbe82e098910be04fc00c0f72be72c593f 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -2135,7 +2135,7 @@ public: hlfir::genLoopNest(loc, builder, shape, !mustBeOrdered); mlir::ValueRange oneBasedIndices = loopNest.oneBasedIndices; auto insPt = builder.saveInsertionPoint(); - builder.setInsertionPointToStart(loopNest.innerLoop.getBody()); + builder.setInsertionPointToStart(loopNest.body); callContext.stmtCtx.pushScope(); for (auto &preparedActual : loweredActuals) if (preparedActual) diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index 72b9018f2d2808e9bcbc1fc2bed3d28cac8d0578..0f2e849c2c6a0e292e42d34dcfca3ffe559edc50 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -98,6 +98,25 @@ genAllocateClause(lower::AbstractConverter &converter, genObjectList(objects, converter, allocateOperands); } +static mlir::omp::ClauseBindKindAttr +genBindKindAttr(fir::FirOpBuilder &firOpBuilder, + const omp::clause::Bind &clause) { + mlir::omp::ClauseBindKind bindKind; + switch (clause.v) { + case omp::clause::Bind::Binding::Teams: + bindKind = mlir::omp::ClauseBindKind::Teams; + break; + case omp::clause::Bind::Binding::Parallel: + bindKind = mlir::omp::ClauseBindKind::Parallel; + break; + case omp::clause::Bind::Binding::Thread: + bindKind = mlir::omp::ClauseBindKind::Thread; + break; + } + return mlir::omp::ClauseBindKindAttr::get(firOpBuilder.getContext(), + bindKind); +} + static mlir::omp::ClauseProcBindKindAttr genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder, const omp::clause::ProcBind &clause) { @@ -139,9 +158,10 @@ genDependKindAttr(lower::AbstractConverter &converter, break; case omp::clause::DependenceType::Mutexinoutset: case omp::clause::DependenceType::Inoutset: - TODO(currentLocation, "INOUTSET and MUTEXINOUTSET are not supported yet"); - break; case omp::clause::DependenceType::Depobj: + TODO(currentLocation, + "INOUTSET, MUTEXINOUTSET and DEPOBJ dependence-types"); + break; case omp::clause::DependenceType::Sink: case omp::clause::DependenceType::Source: llvm_unreachable("unhandled parser task dependence type"); @@ -204,6 +224,15 @@ static void convertLoopBounds(lower::AbstractConverter &converter, // ClauseProcessor unique clauses //===----------------------------------------------------------------------===// +bool ClauseProcessor::processBind(mlir::omp::BindClauseOps &result) const { + if (auto *clause = findUniqueClause()) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + result.bindKind = genBindKindAttr(firOpBuilder, *clause); + return true; + } + return false; +} + bool ClauseProcessor::processCollapse( mlir::Location currentLocation, lower::pft::Evaluation &eval, mlir::omp::LoopRelatedClauseOps &result, @@ -894,14 +923,15 @@ void ClauseProcessor::processMapObjects( lower::StatementContext &stmtCtx, mlir::Location clauseLocation, const omp::ObjectList &objects, llvm::omp::OpenMPOffloadMappingFlags mapTypeBits, - std::map> &parentMemberIndices, + std::map &parentMemberIndices, llvm::SmallVectorImpl &mapVars, llvm::SmallVectorImpl &mapSyms) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + for (const omp::Object &object : objects) { llvm::SmallVector bounds; std::stringstream asFortran; + std::optional parentObj; lower::AddrAndBoundsInfo info = lower::gatherDataOperandAddrAndBoundsowner().IsDerivedType()) { + omp::ObjectList objectList = gatherObjectsOf(object, semaCtx); + assert(!objectList.empty() && + "could not find parent objects of derived type member"); + parentObj = objectList[0]; + parentMemberIndices.emplace(parentObj.value(), + OmpMapParentAndMemberData{}); + + if (isMemberOrParentAllocatableOrPointer(object, semaCtx)) { + llvm::SmallVector indices; + generateMemberPlacementIndices(object, indices, semaCtx); + baseOp = createParentSymAndGenIntermediateMaps( + clauseLocation, converter, semaCtx, stmtCtx, objectList, indices, + parentMemberIndices[parentObj.value()], asFortran.str(), + mapTypeBits); + } + } + // Explicit map captures are captured ByRef by default, // optimisation passes may alter this to ByCopy or other capture // types to optimise - mlir::Value baseOp = info.rawInput; auto location = mlir::NameLoc::get( mlir::StringAttr::get(firOpBuilder.getContext(), asFortran.str()), baseOp.getLoc()); mlir::omp::MapInfoOp mapOp = createMapInfoOp( firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, asFortran.str(), bounds, - /*members=*/{}, /*membersIndex=*/mlir::DenseIntElementsAttr{}, + /*members=*/{}, /*membersIndex=*/mlir::ArrayAttr{}, static_cast< std::underlying_type_t>( mapTypeBits), mlir::omp::VariableCaptureKind::ByRef, baseOp.getType()); - if (object.sym()->owner().IsDerivedType()) { - addChildIndexAndMapToParent(object, parentMemberIndices, mapOp, semaCtx); + if (parentObj.has_value()) { + parentMemberIndices[parentObj.value()].addChildIndexAndMapToParent( + object, mapOp, semaCtx); } else { mapVars.push_back(mapOp); mapSyms.push_back(object.sym()); @@ -945,9 +994,7 @@ bool ClauseProcessor::processMap( llvm::SmallVector localMapSyms; llvm::SmallVectorImpl *ptrMapSyms = mapSyms ? mapSyms : &localMapSyms; - std::map> - parentMemberIndices; + std::map parentMemberIndices; auto process = [&](const omp::clause::Map &clause, const parser::CharBlock &source) { @@ -1007,17 +1054,15 @@ bool ClauseProcessor::processMap( }; bool clauseFound = findRepeatableClause(process); - insertChildMapInfoIntoParent(converter, parentMemberIndices, result.mapVars, - *ptrMapSyms); + insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices, + result.mapVars, *ptrMapSyms); return clauseFound; } bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx, mlir::omp::MapClauseOps &result) { - std::map> - parentMemberIndices; + std::map parentMemberIndices; llvm::SmallVector mapSymbols; auto callbackFn = [&](const auto &clause, const parser::CharBlock &source) { @@ -1044,8 +1089,9 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx, clauseFound = findRepeatableClause(callbackFn) || clauseFound; - insertChildMapInfoIntoParent(converter, parentMemberIndices, result.mapVars, - mapSymbols); + insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices, + result.mapVars, mapSymbols); + return clauseFound; } @@ -1107,9 +1153,7 @@ bool ClauseProcessor::processEnter( bool ClauseProcessor::processUseDeviceAddr( lower::StatementContext &stmtCtx, mlir::omp::UseDeviceAddrClauseOps &result, llvm::SmallVectorImpl &useDeviceSyms) const { - std::map> - parentMemberIndices; + std::map parentMemberIndices; bool clauseFound = findRepeatableClause( [&](const omp::clause::UseDeviceAddr &clause, const parser::CharBlock &source) { @@ -1122,7 +1166,7 @@ bool ClauseProcessor::processUseDeviceAddr( useDeviceSyms); }); - insertChildMapInfoIntoParent(converter, parentMemberIndices, + insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices, result.useDeviceAddrVars, useDeviceSyms); return clauseFound; } @@ -1130,9 +1174,8 @@ bool ClauseProcessor::processUseDeviceAddr( bool ClauseProcessor::processUseDevicePtr( lower::StatementContext &stmtCtx, mlir::omp::UseDevicePtrClauseOps &result, llvm::SmallVectorImpl &useDeviceSyms) const { - std::map> - parentMemberIndices; + std::map parentMemberIndices; + bool clauseFound = findRepeatableClause( [&](const omp::clause::UseDevicePtr &clause, const parser::CharBlock &source) { @@ -1145,7 +1188,7 @@ bool ClauseProcessor::processUseDevicePtr( useDeviceSyms); }); - insertChildMapInfoIntoParent(converter, parentMemberIndices, + insertChildMapInfoIntoParent(converter, semaCtx, stmtCtx, parentMemberIndices, result.useDevicePtrVars, useDeviceSyms); return clauseFound; } diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index f34121c70d0b4495447301aacc391bc48b06aaf4..217d7c6917bd613fc3b77061c2882b13323e6da5 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -53,6 +53,7 @@ public: : converter(converter), semaCtx(semaCtx), clauses(clauses) {} // 'Unique' clauses: They can appear at most once in the clause list. + bool processBind(mlir::omp::BindClauseOps &result) const; bool processCollapse(mlir::Location currentLocation, lower::pft::Evaluation &eval, mlir::omp::LoopRelatedClauseOps &result, @@ -166,8 +167,7 @@ private: lower::StatementContext &stmtCtx, mlir::Location clauseLocation, const omp::ObjectList &objects, llvm::omp::OpenMPOffloadMappingFlags mapTypeBits, - std::map> &parentMemberIndices, + std::map &parentMemberIndices, llvm::SmallVectorImpl &mapVars, llvm::SmallVectorImpl &mapSyms) const; diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 3dedd4864bafc57a070e004b83abc606c4a2502f..eddc742d4c095b7f623f009bc69e3c9e7fe10c66 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -10,6 +10,7 @@ #include "flang/Common/idioms.h" #include "flang/Evaluate/expression.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" #include "flang/Semantics/symbol.h" @@ -264,7 +265,7 @@ makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp, return specifiers; } -Iterator makeIterator(const parser::OmpIteratorModifier &inp, +Iterator makeIterator(const parser::OmpIterator &inp, semantics::SemanticsContext &semaCtx) { Iterator iterator; for (auto &&spec : inp.v) @@ -324,8 +325,9 @@ makeProcedureDesignator(const parser::ProcedureDesignator &inp, inp.u)}; } -ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp, - semantics::SemanticsContext &semaCtx) { +ReductionOperator +makeReductionOperator(const parser::OmpReductionIdentifier &inp, + semantics::SemanticsContext &semaCtx) { return Fortran::common::visit( common::visitors{ [&](const parser::DefinedOperator &s) { @@ -340,9 +342,9 @@ ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp, clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) { switch (inp.v) { - case parser::OmpDependenceType::Type::Sink: + case parser::OmpDependenceType::Value::Sink: return clause::DependenceType::Sink; - case parser::OmpDependenceType::Type::Source: + case parser::OmpDependenceType::Value::Source: return clause::DependenceType::Source; } llvm_unreachable("Unexpected dependence type"); @@ -350,17 +352,17 @@ clause::DependenceType makeDepType(const parser::OmpDependenceType &inp) { clause::DependenceType makeDepType(const parser::OmpTaskDependenceType &inp) { switch (inp.v) { - case parser::OmpTaskDependenceType::Type::Depobj: + case parser::OmpTaskDependenceType::Value::Depobj: return clause::DependenceType::Depobj; - case parser::OmpTaskDependenceType::Type::In: + case parser::OmpTaskDependenceType::Value::In: return clause::DependenceType::In; - case parser::OmpTaskDependenceType::Type::Inout: + case parser::OmpTaskDependenceType::Value::Inout: return clause::DependenceType::Inout; - case parser::OmpTaskDependenceType::Type::Inoutset: + case parser::OmpTaskDependenceType::Value::Inoutset: return clause::DependenceType::Inoutset; - case parser::OmpTaskDependenceType::Type::Mutexinoutset: + case parser::OmpTaskDependenceType::Value::Mutexinoutset: return clause::DependenceType::Mutexinoutset; - case parser::OmpTaskDependenceType::Type::Out: + case parser::OmpTaskDependenceType::Value::Out: return clause::DependenceType::Out; } llvm_unreachable("Unexpected task dependence type"); @@ -381,7 +383,7 @@ Absent make(const parser::OmpClause::Absent &inp, Affinity make(const parser::OmpClause::Affinity &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpAffinityClause - auto &t0 = std::get>(inp.v.t); + auto &t0 = std::get>(inp.v.t); auto &t1 = std::get(inp.v.t); auto &&maybeIter = @@ -489,8 +491,19 @@ AtomicDefaultMemOrder make(const parser::OmpClause::AtomicDefaultMemOrder &inp, Bind make(const parser::OmpClause::Bind &inp, semantics::SemanticsContext &semaCtx) { - // inp -> empty - llvm_unreachable("Empty: bind"); + // inp.v -> parser::OmpBindClause + using wrapped = parser::OmpBindClause; + + CLAUSET_ENUM_CONVERT( // + convert, wrapped::Type, Bind::Binding, + // clang-format off + MS(Teams, Teams) + MS(Parallel, Parallel) + MS(Thread, Thread) + // clang-format on + ); + + return Bind{/*Binding=*/convert(inp.v.v)}; } // CancellationConstructType: empty @@ -561,17 +574,20 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp, CLAUSET_ENUM_CONVERT( // convert2, wrapped::VariableCategory, Defaultmap::VariableCategory, // clang-format off - MS(Scalar, Scalar) MS(Aggregate, Aggregate) - MS(Pointer, Pointer) + MS(All, All) MS(Allocatable, Allocatable) + MS(Pointer, Pointer) + MS(Scalar, Scalar) // clang-format on ); auto &t0 = std::get(inp.v.t); auto &t1 = std::get>(inp.v.t); + + auto category = t1 ? convert2(*t1) : Defaultmap::VariableCategory::All; return Defaultmap{{/*ImplicitBehavior=*/convert1(t0), - /*VariableCategory=*/maybeApply(convert2, t1)}}; + /*VariableCategory=*/category}}; } Doacross makeDoacross(const parser::OmpDoacross &doa, @@ -612,7 +628,7 @@ Depend make(const parser::OmpClause::Depend &inp, using Variant = decltype(Depend::u); auto visitTaskDep = [&](const wrapped::TaskDep &s) -> Variant { - auto &t0 = std::get>(s.t); + auto &t0 = std::get>(s.t); auto &t1 = std::get(s.t); auto &t2 = std::get(s.t); @@ -755,8 +771,7 @@ From make(const parser::OmpClause::From &inp, ); auto &t0 = std::get>>(inp.v.t); - auto &t1 = - std::get>>(inp.v.t); + auto &t1 = std::get>>(inp.v.t); auto &t2 = std::get(inp.v.t); assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed"); @@ -867,7 +882,7 @@ Init make(const parser::OmpClause::Init &inp, InReduction make(const parser::OmpClause::InReduction &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpInReductionClause - auto &t0 = std::get(inp.v.t); + auto &t0 = std::get(inp.v.t); auto &t1 = std::get(inp.v.t); return InReduction{ {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, @@ -906,7 +921,7 @@ Linear make(const parser::OmpClause::Linear &inp, using wrapped = parser::OmpLinearClause; CLAUSET_ENUM_CONVERT( // - convert, parser::OmpLinearModifier::Type, Linear::LinearModifier, + convert, parser::OmpLinearModifier::Value, Linear::LinearModifier, // clang-format off MS(Ref, Ref) MS(Val, Val) @@ -970,10 +985,13 @@ Map make(const parser::OmpClause::Map &inp, ); auto &t0 = std::get>>(inp.v.t); - auto &t1 = - std::get>>(inp.v.t); + auto &t1 = std::get>>(inp.v.t); auto &t2 = std::get>>(inp.v.t); auto &t3 = std::get(inp.v.t); + auto &t4 = std::get(inp.v.t); + + if (t4.v) + TODO_NOLOC("OmpMapClause(MAPPER(...)): user defined mapper not supported"); // These should have been diagnosed already. assert((!t1 || t1->size() == 1) && "Only one iterator modifier is allowed"); @@ -1174,7 +1192,7 @@ Reduction make(const parser::OmpClause::Reduction &inp, auto &t0 = std::get>( inp.v.t); - auto &t1 = std::get(inp.v.t); + auto &t1 = std::get(inp.v.t); auto &t2 = std::get(inp.v.t); return Reduction{ {/*ReductionModifier=*/t0 @@ -1301,7 +1319,7 @@ Permutation make(const parser::OmpClause::Permutation &inp, TaskReduction make(const parser::OmpClause::TaskReduction &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpReductionClause - auto &t0 = std::get(inp.v.t); + auto &t0 = std::get(inp.v.t); auto &t1 = std::get(inp.v.t); return TaskReduction{ {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, @@ -1330,8 +1348,7 @@ To make(const parser::OmpClause::To &inp, ); auto &t0 = std::get>>(inp.v.t); - auto &t1 = - std::get>>(inp.v.t); + auto &t1 = std::get>>(inp.v.t); auto &t2 = std::get(inp.v.t); assert((!t0 || t0->size() == 1) && "Only one expectation modifier allowed"); diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h index 514f0d1ee466acb0851020d271da29dc601c6ac6..ada50e0488837b96fcd8adefc0831f4131e2afd4 100644 --- a/flang/lib/Lower/OpenMP/Clauses.h +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -51,6 +51,13 @@ struct IdTyTemplate { return designator == other.designator; } + // Defining an "ordering" which allows types derived from this to be + // utilised in maps and other containers that require comparison + // operators for ordering + bool operator<(const IdTyTemplate &other) const { + return symbol < other.symbol; + } + operator bool() const { return symbol != nullptr; } }; @@ -72,6 +79,10 @@ struct ObjectT, Fortran::semantics::Symbol *sym() const { return identity.symbol; } const std::optional &ref() const { return identity.designator; } + bool operator<(const ObjectT &other) const { + return identity < other.identity; + } + IdTy identity; }; } // namespace tomp::type diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 91f99ba4b0ca55f6708a70d80ea138cd35003341..a2779213a1a15a30ff2b0256d737029581a5c82f 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -30,6 +30,7 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Parser/characters.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/openmp-directive-sets.h" #include "flang/Semantics/tools.h" @@ -1028,7 +1029,7 @@ static void genBodyOfTargetOp( firOpBuilder, copyVal.getLoc(), copyVal, /*varPtrPtr=*/mlir::Value{}, name.str(), bounds, /*members=*/llvm::SmallVector{}, - /*membersIndex=*/mlir::DenseIntElementsAttr{}, + /*membersIndex=*/mlir::ArrayAttr{}, static_cast< std::underlying_type_t>( llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT), @@ -1176,6 +1177,18 @@ genLoopNestClauses(lower::AbstractConverter &converter, clauseOps.loopInclusive = converter.getFirOpBuilder().getUnitAttr(); } +static void genLoopClauses( + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + const List &clauses, mlir::Location loc, + mlir::omp::LoopOperands &clauseOps, + llvm::SmallVectorImpl &reductionSyms) { + ClauseProcessor cp(converter, semaCtx, clauses); + cp.processBind(clauseOps); + cp.processOrder(clauseOps); + cp.processReduction(loc, clauseOps, reductionSyms); + cp.processTODO(loc, llvm::omp::Directive::OMPD_loop); +} + static void genMaskedClauses(lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, lower::StatementContext &stmtCtx, @@ -1359,6 +1372,15 @@ static void genTaskwaitClauses(lower::AbstractConverter &converter, loc, llvm::omp::Directive::OMPD_taskwait); } +static void genWorkshareClauses(lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, + const List &clauses, mlir::Location loc, + mlir::omp::WorkshareOperands &clauseOps) { + ClauseProcessor cp(converter, semaCtx, clauses); + cp.processNowait(clauseOps); +} + static void genTeamsClauses(lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, lower::StatementContext &stmtCtx, @@ -1473,6 +1495,40 @@ static mlir::omp::LoopNestOp genLoopNestOp( queue, item, clauseOps); } +static void genLoopOp(lower::AbstractConverter &converter, + lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, + ConstructQueue::const_iterator item) { + mlir::omp::LoopOperands loopClauseOps; + llvm::SmallVector loopReductionSyms; + genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps, + loopReductionSyms); + + DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval, + /*shouldCollectPreDeterminedSymbols=*/true, + /*useDelayedPrivatization=*/true, &symTable); + dsp.processStep1(&loopClauseOps); + + mlir::omp::LoopNestOperands loopNestClauseOps; + llvm::SmallVector iv; + genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc, + loopNestClauseOps, iv); + + EntryBlockArgs loopArgs; + loopArgs.priv.syms = dsp.getDelayedPrivSymbols(); + loopArgs.priv.vars = loopClauseOps.privateVars; + loopArgs.reduction.syms = loopReductionSyms; + loopArgs.reduction.vars = loopClauseOps.reductionVars; + + auto loopOp = + genWrapperOp(converter, loc, loopClauseOps, loopArgs); + genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item, + loopNestClauseOps, iv, {{loopOp, loopArgs}}, + llvm::omp::Directive::OMPD_loop, dsp); +} + static mlir::omp::MaskedOp genMaskedOp(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, @@ -1818,7 +1874,7 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable, mlir::Value mapOp = createMapInfoOp( firOpBuilder, location, baseOp, /*varPtrPtr=*/mlir::Value{}, name.str(), bounds, /*members=*/{}, - /*membersIndex=*/mlir::DenseIntElementsAttr{}, + /*membersIndex=*/mlir::ArrayAttr{}, static_cast< std::underlying_type_t>( mapFlag), @@ -1986,6 +2042,24 @@ genTaskyieldOp(lower::AbstractConverter &converter, lower::SymMap &symTable, return converter.getFirOpBuilder().create(loc); } +static mlir::omp::WorkshareOp +genWorkshareOp(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, mlir::Location loc, + const ConstructQueue &queue, + ConstructQueue::const_iterator item) { + lower::StatementContext stmtCtx; + mlir::omp::WorkshareOperands clauseOps; + genWorkshareClauses(converter, semaCtx, stmtCtx, item->clauses, loc, + clauseOps); + + return genOpWithBody( + OpWithBodyGenInfo(converter, symTable, semaCtx, loc, eval, + llvm::omp::Directive::OMPD_workshare) + .setClauses(&item->clauses), + queue, item, clauseOps); +} + static mlir::omp::TeamsOp genTeamsOp(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, @@ -2505,7 +2579,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter, genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_loop: - TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir)); + genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item); break; case llvm::omp::Directive::OMPD_masked: genMaskedOp(converter, symTable, semaCtx, eval, loc, queue, item); @@ -2520,6 +2594,9 @@ static void genOMPDispatch(lower::AbstractConverter &converter, case llvm::omp::Directive::OMPD_parallel: genStandaloneParallel(converter, symTable, semaCtx, eval, loc, queue, item); break; + case llvm::omp::Directive::OMPD_scan: + TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir)); + break; case llvm::omp::Directive::OMPD_section: llvm_unreachable("genOMPDispatch: OMPD_section"); // Lowered in the enclosing genSectionsOp. @@ -2581,10 +2658,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter, llvm::omp::getOpenMPDirectiveName(dir) + ")"); // case llvm::omp::Directive::OMPD_workdistribute: case llvm::omp::Directive::OMPD_workshare: - // FIXME: Workshare is not a commonly used OpenMP construct, an - // implementation for this feature will come later. For the codes - // that use this construct, add a single construct for now. - genSingleOp(converter, symTable, semaCtx, eval, loc, queue, item); + genWorkshareOp(converter, symTable, semaCtx, eval, loc, queue, item); break; default: // Combined and composite constructs should have been split into a sequence @@ -2623,6 +2697,13 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct"); } +static void +genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + const parser::OpenMPDeclareMapperConstruct &declareMapperConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPDeclareMapperConstruct"); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, @@ -2871,7 +2952,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u)) { - TODO(clauseLocation, "OpenMP Block construct clause"); + std::string name = + parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(clause.id)); + TODO(clauseLocation, name + " clause is not implemented yet"); } } diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index 6b98ea3d0615b667bd16e5305f46ea2e05f69310..736de2ee511befc2404ce9ee853af01f427d3e8e 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -374,7 +374,7 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, // know this won't miss any opportuinties for clever elemental inlining hlfir::LoopNest nest = hlfir::genLoopNest( loc, builder, shapeShift.getExtents(), /*isUnordered=*/true); - builder.setInsertionPointToStart(nest.innerLoop.getBody()); + builder.setInsertionPointToStart(nest.body); mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); auto lhsEleAddr = builder.create( loc, refTy, lhs, shapeShift, /*slice=*/mlir::Value{}, @@ -388,7 +388,7 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, builder, loc, redId, refTy, lhsEle, rhsEle); builder.create(loc, scalarReduction, lhsEleAddr); - builder.setInsertionPointAfter(nest.outerLoop); + builder.setInsertionPointAfter(nest.outerOp); builder.create(loc, lhsAddr); } diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index a09d91540ec22203c243d99e9836bb112b758d08..5340dd8c5fb9a25ff886d0bd2c2c0c1eddd52eeb 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -13,6 +13,8 @@ #include "Utils.h" #include "Clauses.h" +#include + #include #include #include @@ -23,8 +25,7 @@ #include #include -#include -#include +#include llvm::cl::opt treatIndexAsSection( "openmp-treat-index-as-section", @@ -119,10 +120,10 @@ void gatherFuncAndVarSyms( mlir::omp::MapInfoOp createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name, - llvm::ArrayRef bounds, + mlir::Value baseAddr, mlir::Value varPtrPtr, + llvm::StringRef name, llvm::ArrayRef bounds, llvm::ArrayRef members, - mlir::DenseIntElementsAttr membersIndex, uint64_t mapType, + mlir::ArrayAttr membersIndex, uint64_t mapType, mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, bool partialMap) { if (auto boxTy = llvm::dyn_cast(baseAddr.getType())) { @@ -145,11 +146,294 @@ createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, builder.getIntegerAttr(builder.getIntegerType(64, false), mapType), builder.getAttr(mapCaptureType), builder.getStringAttr(name), builder.getBoolAttr(partialMap)); - return op; } -static int +// This function gathers the individual omp::Object's that make up a +// larger omp::Object symbol. +// +// For example, provided the larger symbol: "parent%child%member", this +// function breaks it up into its constituent components ("parent", +// "child", "member"), so we can access each individual component and +// introspect details. Important to note is this function breaks it up from +// RHS to LHS ("member" to "parent") and then we reverse it so that the +// returned omp::ObjectList is LHS to RHS, with the "parent" at the +// beginning. +omp::ObjectList gatherObjectsOf(omp::Object derivedTypeMember, + semantics::SemanticsContext &semaCtx) { + omp::ObjectList objList; + std::optional baseObj = derivedTypeMember; + while (baseObj.has_value()) { + objList.push_back(baseObj.value()); + baseObj = getBaseObject(baseObj.value(), semaCtx); + } + return omp::ObjectList{llvm::reverse(objList)}; +} + +// This function generates a series of indices from a provided omp::Object, +// that devolves to an ArrayRef symbol, e.g. "array(2,3,4)", this function +// would generate a series of indices of "[1][2][3]" for the above example, +// offsetting by -1 to account for the non-zero fortran indexes. +// +// These indices can then be provided to a coordinate operation or other +// GEP-like operation to access the relevant positional member of the +// array. +// +// It is of note that the function only supports subscript integers currently +// and not Triplets i.e. Array(1:2:3). +static void generateArrayIndices(lower::AbstractConverter &converter, + fir::FirOpBuilder &firOpBuilder, + lower::StatementContext &stmtCtx, + mlir::Location clauseLocation, + llvm::SmallVectorImpl &indices, + omp::Object object) { + auto maybeRef = evaluate::ExtractDataRef(*object.ref()); + if (!maybeRef) + return; + + auto *arr = std::get_if(&maybeRef->u); + if (!arr) + return; + + for (auto v : arr->subscript()) { + if (std::holds_alternative(v.u)) + TODO(clauseLocation, "Triplet indexing in map clause is unsupported"); + + auto expr = std::get(v.u); + mlir::Value subscript = + fir::getBase(converter.genExprValue(toEvExpr(expr.value()), stmtCtx)); + mlir::Value one = firOpBuilder.createIntegerConstant( + clauseLocation, firOpBuilder.getIndexType(), 1); + subscript = firOpBuilder.createConvert( + clauseLocation, firOpBuilder.getIndexType(), subscript); + indices.push_back(firOpBuilder.create(clauseLocation, + subscript, one)); + } +} + +/// When mapping members of derived types, there is a chance that one of the +/// members along the way to a mapped member is an descriptor. In which case +/// we have to make sure we generate a map for those along the way otherwise +/// we will be missing a chunk of data required to actually map the member +/// type to device. This function effectively generates these maps and the +/// appropriate data accesses required to generate these maps. It will avoid +/// creating duplicate maps, as duplicates are just as bad as unmapped +/// descriptor data in a lot of cases for the runtime (and unnecessary +/// data movement should be avoided where possible). +/// +/// As an example for the following mapping: +/// +/// type :: vertexes +/// integer(4), allocatable :: vertexx(:) +/// integer(4), allocatable :: vertexy(:) +/// end type vertexes +/// +/// type :: dtype +/// real(4) :: i +/// type(vertexes), allocatable :: vertexes(:) +/// end type dtype +/// +/// type(dtype), allocatable :: alloca_dtype +/// +/// !$omp target map(tofrom: alloca_dtype%vertexes(N1)%vertexx) +/// +/// The below HLFIR/FIR is generated (trimmed for conciseness): +/// +/// On the first iteration we index into the record type alloca_dtype +/// to access "vertexes", we then generate a map for this descriptor +/// alongside bounds to indicate we only need the 1 member, rather than +/// the whole array block in this case (In theory we could map its +/// entirety at the cost of data transfer bandwidth). +/// +/// %13:2 = hlfir.declare ... "alloca_dtype" ... +/// %39 = fir.load %13#0 : ... +/// %40 = fir.coordinate_of %39, %c1 : ... +/// %51 = omp.map.info var_ptr(%40 : ...) map_clauses(to) capture(ByRef) ... +/// %52 = fir.load %40 : ... +/// +/// Second iteration generating access to "vertexes(N1) utilising the N1 index +/// %53 = load N1 ... +/// %54 = fir.convert %53 : (i32) -> i64 +/// %55 = fir.convert %54 : (i64) -> index +/// %56 = arith.subi %55, %c1 : index +/// %57 = fir.coordinate_of %52, %56 : ... +/// +/// Still in the second iteration we access the allocatable member "vertexx", +/// we return %58 from the function and provide it to the final and "main" +/// map of processMap (generated by the record type segment of the below +/// function), if this were not the final symbol in the list, i.e. we accessed +/// a member below vertexx, we would have generated the map below as we did in +/// the first iteration and then continue to generate further coordinates to +/// access further components as required. +/// +/// %58 = fir.coordinate_of %57, %c0 : ... +/// %61 = omp.map.info var_ptr(%58 : ...) map_clauses(to) capture(ByRef) ... +/// +/// Parent mapping containing prior generated mapped members, generated at +/// a later step but here to showcase the "end" result +/// +/// omp.map.info var_ptr(%13#1 : ...) map_clauses(to) capture(ByRef) +/// members(%50, %61 : [0, 1, 0], [0, 1, 0] : ... +/// +/// \param objectList - The list of omp::Object symbol data for each parent +/// to the mapped member (also includes the mapped member), generated via +/// gatherObjectsOf. +/// \param indices - List of index data associated with the mapped member +/// symbol, which identifies the placement of the member in its parent, +/// this helps generate the appropriate member accesses. These indices +/// can be generated via generateMemberPlacementIndices. +/// \param asFortran - A string generated from the mapped variable to be +/// associated with the main map, generally (but not restricted to) +/// generated via gatherDataOperandAddrAndBounds or other +/// DirectiveCommons.hpp utilities. +/// \param mapTypeBits - The map flags that will be associated with the +/// generated maps, minus alterations of the TO and FROM bits for the +/// intermediate components to prevent accidental overwriting on device +/// write back. +mlir::Value createParentSymAndGenIntermediateMaps( + mlir::Location clauseLocation, lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, lower::StatementContext &stmtCtx, + omp::ObjectList &objectList, llvm::SmallVectorImpl &indices, + OmpMapParentAndMemberData &parentMemberIndices, llvm::StringRef asFortran, + llvm::omp::OpenMPOffloadMappingFlags mapTypeBits) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + + /// Checks if an omp::Object is an array expression with a subscript, e.g. + /// array(1,2). + auto isArrayExprWithSubscript = [](omp::Object obj) { + if (auto maybeRef = evaluate::ExtractDataRef(*obj.ref())) { + evaluate::DataRef ref = *maybeRef; + if (auto *arr = std::get_if(&ref.u)) + return !arr->subscript().empty(); + } + return false; + }; + + // Generate the access to the original parent base address. + lower::AddrAndBoundsInfo parentBaseAddr = lower::getDataOperandBaseAddr( + converter, firOpBuilder, *objectList[0].sym(), clauseLocation); + mlir::Value curValue = parentBaseAddr.addr; + + // Iterate over all objects in the objectList, this should consist of all + // record types between the parent and the member being mapped (including + // the parent). The object list may also contain array objects as well, + // this can occur when specifying bounds or a specific element access + // within a member map, we skip these. + size_t currentIndicesIdx = 0; + for (size_t i = 0; i < objectList.size(); ++i) { + // If we encounter a sequence type, i.e. an array, we must generate the + // correct coordinate operation to index into the array to proceed further, + // this is only relevant in cases where we encounter subscripts currently. + // + // For example in the following case: + // + // map(tofrom: array_dtype(4)%internal_dtypes(3)%float_elements(4)) + // + // We must generate coordinate operation accesses for each subscript + // we encounter. + if (fir::SequenceType arrType = mlir::dyn_cast( + fir::unwrapPassByRefType(curValue.getType()))) { + if (isArrayExprWithSubscript(objectList[i])) { + llvm::SmallVector subscriptIndices; + generateArrayIndices(converter, firOpBuilder, stmtCtx, clauseLocation, + subscriptIndices, objectList[i]); + assert(!subscriptIndices.empty() && + "missing expected indices for map clause"); + curValue = firOpBuilder.create( + clauseLocation, firOpBuilder.getRefType(arrType.getEleTy()), + curValue, subscriptIndices); + } + } + + // If we encounter a record type, we must access the subsequent member + // by indexing into it and creating a coordinate operation to do so, we + // utilise the index information generated previously and passed in to + // work out the correct member to access and the corresponding member + // type. + if (fir::RecordType recordType = mlir::dyn_cast( + fir::unwrapPassByRefType(curValue.getType()))) { + mlir::Value idxConst = firOpBuilder.createIntegerConstant( + clauseLocation, firOpBuilder.getIndexType(), + indices[currentIndicesIdx]); + mlir::Type memberTy = + recordType.getTypeList().at(indices[currentIndicesIdx]).second; + curValue = firOpBuilder.create( + clauseLocation, firOpBuilder.getRefType(memberTy), curValue, + idxConst); + + // Skip mapping and the subsequent load if we're the final member or not + // a type with a descriptor such as a pointer/allocatable. If we're a + // final member, the map will be generated by the processMap call that + // invoked this function, and if we're not a type with a descriptor then + // we have no need of generating an intermediate map for it, as we only + // need to generate a map if a member is a descriptor type (and thus + // obscures the members it contains via a pointer in which it's data needs + // mapped) + if ((currentIndicesIdx == indices.size() - 1) || + !fir::isTypeWithDescriptor(memberTy)) { + currentIndicesIdx++; + continue; + } + + llvm::SmallVector interimIndices( + indices.begin(), std::next(indices.begin(), currentIndicesIdx + 1)); + // Verify we haven't already created a map for this particular member, by + // checking the list of members already mapped for the current parent, + // stored in the parentMemberIndices structure + if (!parentMemberIndices.isDuplicateMemberMapInfo(interimIndices)) { + // Generate bounds operations using the standard lowering utility, + // unfortunately this currently does a bit more than just generate + // bounds and we discard the other bits. May be useful to extend the + // utility to just provide bounds in the future. + llvm::SmallVector interimBounds; + if (i + 1 < objectList.size() && + objectList[i + 1].sym()->IsObjectArray()) { + std::stringstream interimFortran; + Fortran::lower::gatherDataOperandAddrAndBounds< + mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>( + converter, converter.getFirOpBuilder(), semaCtx, + converter.getFctCtx(), *objectList[i + 1].sym(), + objectList[i + 1].ref(), clauseLocation, interimFortran, + interimBounds, treatIndexAsSection); + } + + // Remove all map TO, FROM and TOFROM bits, from the intermediate + // allocatable maps, we simply wish to alloc or release them. It may be + // safer to just pass OMP_MAP_NONE as the map type, but we may still + // need some of the other map types the mapped member utilises, so for + // now it's good to keep an eye on this. + llvm::omp::OpenMPOffloadMappingFlags interimMapType = mapTypeBits; + interimMapType &= ~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; + interimMapType &= ~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; + + // Create a map for the intermediate member and insert it and it's + // indices into the parentMemberIndices list to track it. + mlir::omp::MapInfoOp mapOp = createMapInfoOp( + firOpBuilder, clauseLocation, curValue, + /*varPtrPtr=*/mlir::Value{}, asFortran, + /*bounds=*/interimBounds, + /*members=*/{}, + /*membersIndex=*/mlir::ArrayAttr{}, + static_cast< + std::underlying_type_t>( + interimMapType), + mlir::omp::VariableCaptureKind::ByRef, curValue.getType()); + + parentMemberIndices.memberPlacementIndices.push_back(interimIndices); + parentMemberIndices.memberMap.push_back(mapOp); + } + + // Load the currently accessed member, so we can continue to access + // further segments. + curValue = firOpBuilder.create(clauseLocation, curValue); + currentIndicesIdx++; + } + } + + return curValue; +} + +static int64_t getComponentPlacementInParent(const semantics::Symbol *componentSym) { const auto *derived = componentSym->owner() .derivedTypeSpec() @@ -183,101 +467,66 @@ getComponentObject(std::optional object, return getComponentObject(baseObj.value(), semaCtx); } -static void -generateMemberPlacementIndices(const Object &object, - llvm::SmallVectorImpl &indices, - semantics::SemanticsContext &semaCtx) { +void generateMemberPlacementIndices(const Object &object, + llvm::SmallVectorImpl &indices, + semantics::SemanticsContext &semaCtx) { + assert(indices.empty() && "indices vector passed to " + "generateMemberPlacementIndices should be empty"); auto compObj = getComponentObject(object, semaCtx); + while (compObj) { - indices.push_back(getComponentPlacementInParent(compObj->sym())); + int64_t index = getComponentPlacementInParent(compObj->sym()); + assert( + index >= 0 && + "unexpected index value returned from getComponentPlacementInParent"); + indices.push_back(index); compObj = getComponentObject(getBaseObject(compObj.value(), semaCtx), semaCtx); } - indices = llvm::SmallVector{llvm::reverse(indices)}; + indices = llvm::SmallVector{llvm::reverse(indices)}; } -void addChildIndexAndMapToParent( - const omp::Object &object, - std::map> &parentMemberIndices, - mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx) { - std::optional dataRef = ExtractDataRef(object.ref()); - assert(dataRef.has_value() && - "DataRef could not be extracted during mapping of derived type " - "cannot proceed"); - const semantics::Symbol *parentSym = &dataRef->GetFirstSymbol(); - assert(parentSym && "Could not find parent symbol during lower of " - "a component member in OpenMP map clause"); - llvm::SmallVector indices; +void OmpMapParentAndMemberData::addChildIndexAndMapToParent( + const omp::Object &object, mlir::omp::MapInfoOp &mapOp, + semantics::SemanticsContext &semaCtx) { + llvm::SmallVector indices; generateMemberPlacementIndices(object, indices, semaCtx); - parentMemberIndices[parentSym].push_back({indices, mapOp}); + memberPlacementIndices.push_back(indices); + memberMap.push_back(mapOp); } -static void calculateShapeAndFillIndices( - llvm::SmallVectorImpl &shape, - llvm::SmallVectorImpl &memberPlacementData) { - shape.push_back(memberPlacementData.size()); - size_t largestIndicesSize = - std::max_element(memberPlacementData.begin(), memberPlacementData.end(), - [](auto a, auto b) { - return a.memberPlacementIndices.size() < - b.memberPlacementIndices.size(); - }) - ->memberPlacementIndices.size(); - shape.push_back(largestIndicesSize); - - // DenseElementsAttr expects a rectangular shape for the data, so all - // index lists have to be of the same length, this emplaces -1 as filler. - for (auto &v : memberPlacementData) { - if (v.memberPlacementIndices.size() < largestIndicesSize) { - auto *prevEnd = v.memberPlacementIndices.end(); - v.memberPlacementIndices.resize(largestIndicesSize); - std::fill(prevEnd, v.memberPlacementIndices.end(), -1); - } +bool isMemberOrParentAllocatableOrPointer( + const Object &object, semantics::SemanticsContext &semaCtx) { + if (semantics::IsAllocatableOrObjectPointer(object.sym())) + return true; + + auto compObj = getBaseObject(object, semaCtx); + while (compObj) { + if (semantics::IsAllocatableOrObjectPointer(compObj.value().sym())) + return true; + compObj = getBaseObject(compObj.value(), semaCtx); } -} -static mlir::DenseIntElementsAttr createDenseElementsAttrFromIndices( - llvm::SmallVectorImpl &memberPlacementData, - fir::FirOpBuilder &builder) { - llvm::SmallVector shape; - calculateShapeAndFillIndices(shape, memberPlacementData); - - llvm::SmallVector indicesFlattened = - std::accumulate(memberPlacementData.begin(), memberPlacementData.end(), - llvm::SmallVector(), - [](llvm::SmallVector &x, OmpMapMemberIndicesData y) { - x.insert(x.end(), y.memberPlacementIndices.begin(), - y.memberPlacementIndices.end()); - return x; - }); - - return mlir::DenseIntElementsAttr::get( - mlir::VectorType::get(shape, - mlir::IntegerType::get(builder.getContext(), 32)), - indicesFlattened); + return false; } void insertChildMapInfoIntoParent( - lower::AbstractConverter &converter, - std::map> &parentMemberIndices, + lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx, + lower::StatementContext &stmtCtx, + std::map &parentMemberIndices, llvm::SmallVectorImpl &mapOperands, llvm::SmallVectorImpl &mapSyms) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); for (auto indices : parentMemberIndices) { - bool parentExists = false; - size_t parentIdx; - for (parentIdx = 0; parentIdx < mapSyms.size(); ++parentIdx) { - if (mapSyms[parentIdx] == indices.first) { - parentExists = true; - break; - } - } - - if (parentExists) { + auto *parentIter = + llvm::find_if(mapSyms, [&indices](const semantics::Symbol *v) { + return v == indices.first.sym(); + }); + if (parentIter != mapSyms.end()) { auto mapOp = llvm::cast( - mapOperands[parentIdx].getDefiningOp()); + mapOperands[std::distance(mapSyms.begin(), parentIter)] + .getDefiningOp()); // NOTE: To maintain appropriate SSA ordering, we move the parent map // which will now have references to its children after the last @@ -285,71 +534,55 @@ void insertChildMapInfoIntoParent( // has defined a series of parent and children maps where the parent // precedes the children. An alternative, may be to do // delayed generation of map info operations from the clauses and - // organize them first before generation. - mapOp->moveAfter(indices.second.back().memberMap); + // organize them first before generation. Or to use the + // topologicalSort utility which will enforce a stronger SSA + // dominance ordering at the cost of efficiency/time. + mapOp->moveAfter(indices.second.memberMap.back()); - for (auto memberIndicesData : indices.second) - mapOp.getMembersMutable().append( - memberIndicesData.memberMap.getResult()); + for (mlir::omp::MapInfoOp memberMap : indices.second.memberMap) + mapOp.getMembersMutable().append(memberMap.getResult()); - mapOp.setMembersIndexAttr(createDenseElementsAttrFromIndices( - indices.second, converter.getFirOpBuilder())); + mapOp.setMembersIndexAttr(firOpBuilder.create2DI64ArrayAttr( + indices.second.memberPlacementIndices)); } else { // NOTE: We take the map type of the first child, this may not // be the correct thing to do, however, we shall see. For the moment // it allows this to work with enter and exit without causing MLIR // verification issues. The more appropriate thing may be to take // the "main" map type clause from the directive being used. - uint64_t mapType = indices.second[0].memberMap.getMapType().value_or(0); - - // create parent to emplace and bind members - mlir::Value origSymbol = converter.getSymbolAddress(*indices.first); + uint64_t mapType = indices.second.memberMap[0].getMapType().value_or(0); llvm::SmallVector members; - for (OmpMapMemberIndicesData memberIndicesData : indices.second) - members.push_back((mlir::Value)memberIndicesData.memberMap); - - mlir::Value mapOp = createMapInfoOp( - converter.getFirOpBuilder(), origSymbol.getLoc(), origSymbol, - /*varPtrPtr=*/mlir::Value(), indices.first->name().ToString(), - /*bounds=*/{}, members, - createDenseElementsAttrFromIndices(indices.second, - converter.getFirOpBuilder()), - mapType, mlir::omp::VariableCaptureKind::ByRef, origSymbol.getType(), + members.reserve(indices.second.memberMap.size()); + for (mlir::omp::MapInfoOp memberMap : indices.second.memberMap) + members.push_back(memberMap.getResult()); + + // Create parent to emplace and bind members + llvm::SmallVector bounds; + std::stringstream asFortran; + lower::AddrAndBoundsInfo info = + lower::gatherDataOperandAddrAndBounds( + converter, firOpBuilder, semaCtx, converter.getFctCtx(), + *indices.first.sym(), indices.first.ref(), + converter.getCurrentLocation(), asFortran, bounds, + treatIndexAsSection); + + mlir::omp::MapInfoOp mapOp = createMapInfoOp( + firOpBuilder, info.rawInput.getLoc(), info.rawInput, + /*varPtrPtr=*/mlir::Value(), asFortran.str(), bounds, members, + firOpBuilder.create2DI64ArrayAttr( + indices.second.memberPlacementIndices), + mapType, mlir::omp::VariableCaptureKind::ByRef, + info.rawInput.getType(), /*partialMap=*/true); mapOperands.push_back(mapOp); - mapSyms.push_back(indices.first); + mapSyms.push_back(indices.first.sym()); } } } -semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject) { - semantics::Symbol *sym = nullptr; - Fortran::common::visit( - common::visitors{ - [&](const parser::Designator &designator) { - if (auto *arrayEle = - parser::Unwrap(designator)) { - // Use getLastName to retrieve the arrays symbol, this will - // provide the farthest right symbol (the last) in a designator, - // i.e. providing something like the following: - // "dtype1%dtype2%array[2:10]", will result in "array" - sym = GetLastName(arrayEle->base).symbol; - } else if (auto *structComp = - parser::Unwrap( - designator)) { - sym = structComp->component.symbol; - } else if (const parser::Name *name = - semantics::getDesignatorNameIfDataRef(designator)) { - sym = name->symbol; - } - }, - [&](const parser::Name &name) { sym = name.symbol; }}, - ompObject.u); - return sym; -} - void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp, mlir::Location loc) { using Lastprivate = omp::clause::Lastprivate; diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 4a569cd64355d31acf6064510c68399c4129ff71..f2e378443e5f295b79ab5cdafa49ca6ec6ee8b6f 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -14,6 +14,7 @@ #include "mlir/IR/Location.h" #include "mlir/IR/Value.h" #include "llvm/Support/CommandLine.h" +#include extern llvm::cl::opt treatIndexAsSection; extern llvm::cl::opt enableDelayedPrivatization; @@ -34,6 +35,7 @@ struct OmpObjectList; } // namespace parser namespace lower { +class StatementContext; namespace pft { struct Evaluation; } @@ -49,37 +51,98 @@ using DeclareTargetCapturePair = // and index data when lowering OpenMP map clauses. Keeps track of the // placement of the component in the derived type hierarchy it rests within, // alongside the generated mlir::omp::MapInfoOp for the mapped component. -struct OmpMapMemberIndicesData { +// +// As an example of what the contents of this data structure may be like, +// when provided the following derived type and map of that type: +// +// type :: bottom_layer +// real(8) :: i2 +// real(4) :: array_i2(10) +// real(4) :: array_j2(10) +// end type bottom_layer +// +// type :: top_layer +// real(4) :: i +// integer(4) :: array_i(10) +// real(4) :: j +// type(bottom_layer) :: nested +// integer, allocatable :: array_j(:) +// integer(4) :: k +// end type top_layer +// +// type(top_layer) :: top_dtype +// +// map(tofrom: top_dtype%nested%i2, top_dtype%k, top_dtype%nested%array_i2) +// +// We would end up with an OmpMapParentAndMemberData populated like below: +// +// memberPlacementIndices: +// Vector 1: 3, 0 +// Vector 2: 5 +// Vector 3: 3, 1 +// +// memberMap: +// Entry 1: omp.map.info for "top_dtype%nested%i2" +// Entry 2: omp.map.info for "top_dtype%k" +// Entry 3: omp.map.info for "top_dtype%nested%array_i2" +// +// And this OmpMapParentAndMemberData would be accessed via the parent +// symbol for top_dtype. Other parent derived type instances that have +// members mapped would have there own OmpMapParentAndMemberData entry +// accessed via their own symbol. +struct OmpMapParentAndMemberData { // The indices representing the component members placement in its derived // type parents hierarchy. - llvm::SmallVector memberPlacementIndices; + llvm::SmallVector> memberPlacementIndices; // Placement of the member in the member vector. - mlir::omp::MapInfoOp memberMap; + llvm::SmallVector memberMap; + + bool isDuplicateMemberMapInfo(llvm::SmallVectorImpl &memberIndices) { + return llvm::find_if(memberPlacementIndices, [&](auto &memberData) { + return llvm::equal(memberIndices, memberData); + }) != memberPlacementIndices.end(); + } + + void addChildIndexAndMapToParent(const omp::Object &object, + mlir::omp::MapInfoOp &mapOp, + semantics::SemanticsContext &semaCtx); }; mlir::omp::MapInfoOp createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name, - mlir::ArrayRef bounds, - mlir::ArrayRef members, - mlir::DenseIntElementsAttr membersIndex, uint64_t mapType, + mlir::Value baseAddr, mlir::Value varPtrPtr, + llvm::StringRef name, llvm::ArrayRef bounds, + llvm::ArrayRef members, + mlir::ArrayAttr membersIndex, uint64_t mapType, mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, bool partialMap = false); -void addChildIndexAndMapToParent( - const omp::Object &object, - std::map> &parentMemberIndices, - mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx); - void insertChildMapInfoIntoParent( - lower::AbstractConverter &converter, - std::map> &parentMemberIndices, + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::StatementContext &stmtCtx, + std::map &parentMemberIndices, llvm::SmallVectorImpl &mapOperands, llvm::SmallVectorImpl &mapSyms); +void generateMemberPlacementIndices( + const Object &object, llvm::SmallVectorImpl &indices, + Fortran::semantics::SemanticsContext &semaCtx); + +bool isMemberOrParentAllocatableOrPointer( + const Object &object, Fortran::semantics::SemanticsContext &semaCtx); + +mlir::Value createParentSymAndGenIntermediateMaps( + mlir::Location clauseLocation, Fortran::lower::AbstractConverter &converter, + semantics::SemanticsContext &semaCtx, lower::StatementContext &stmtCtx, + omp::ObjectList &objectList, llvm::SmallVectorImpl &indices, + OmpMapParentAndMemberData &parentMemberIndices, llvm::StringRef asFortran, + llvm::omp::OpenMPOffloadMappingFlags mapTypeBits); + +omp::ObjectList gatherObjectsOf(omp::Object derivedTypeMember, + semantics::SemanticsContext &semaCtx); + mlir::Type getLoopVarType(lower::AbstractConverter &converter, std::size_t loopVarTypeSize); @@ -92,8 +155,6 @@ void gatherFuncAndVarSyms( int64_t getCollapseValue(const List &clauses); -semantics::Symbol *getOmpObjectSymbol(const parser::OmpObject &ompObject); - void genObjectList(const ObjectList &objects, lower::AbstractConverter &converter, llvm::SmallVectorImpl &operands); diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 8fa695a5c0c2e1ef6160e70655919dffe7735bbe..3a39c455015f9fd23a088b9da802374778bb98d0 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -267,6 +267,26 @@ mlir::Block *fir::FirOpBuilder::getAllocaBlock() { return getEntryBlock(); } +static mlir::ArrayAttr makeI64ArrayAttr(llvm::ArrayRef values, + mlir::MLIRContext *context) { + llvm::SmallVector attrs; + attrs.reserve(values.size()); + for (auto &v : values) + attrs.push_back(mlir::IntegerAttr::get(mlir::IntegerType::get(context, 64), + mlir::APInt(64, v))); + return mlir::ArrayAttr::get(context, attrs); +} + +mlir::ArrayAttr fir::FirOpBuilder::create2DI64ArrayAttr( + llvm::SmallVectorImpl> &intData) { + llvm::SmallVector arrayAttr; + arrayAttr.reserve(intData.size()); + mlir::MLIRContext *context = getContext(); + for (auto &v : intData) + arrayAttr.push_back(makeI64ArrayAttr(v, context)); + return mlir::ArrayAttr::get(context, arrayAttr); +} + mlir::Value fir::FirOpBuilder::createTemporaryAlloc( mlir::Location loc, mlir::Type type, llvm::StringRef name, mlir::ValueRange lenParams, mlir::ValueRange shape, diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 8d0ae2f195178c826a37a504c2e6065bcd3a07d1..7425ccf7fc0e30c20f662fdf41c19c72529c49e5 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -20,6 +20,7 @@ #include "mlir/IR/IRMapping.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/TypeSwitch.h" +#include #include // Return explicit extents. If the base is a fir.box, this won't read it to @@ -855,26 +856,50 @@ mlir::Value hlfir::inlineElementalOp( hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc, fir::FirOpBuilder &builder, - mlir::ValueRange extents, bool isUnordered) { + mlir::ValueRange extents, bool isUnordered, + bool emitWorkshareLoop) { + emitWorkshareLoop = emitWorkshareLoop && isUnordered; hlfir::LoopNest loopNest; assert(!extents.empty() && "must have at least one extent"); - auto insPt = builder.saveInsertionPoint(); + mlir::OpBuilder::InsertionGuard guard(builder); loopNest.oneBasedIndices.assign(extents.size(), mlir::Value{}); // Build loop nest from column to row. auto one = builder.create(loc, 1); mlir::Type indexType = builder.getIndexType(); - unsigned dim = extents.size() - 1; - for (auto extent : llvm::reverse(extents)) { - auto ub = builder.createConvert(loc, indexType, extent); - loopNest.innerLoop = - builder.create(loc, one, ub, one, isUnordered); - builder.setInsertionPointToStart(loopNest.innerLoop.getBody()); - // Reverse the indices so they are in column-major order. - loopNest.oneBasedIndices[dim--] = loopNest.innerLoop.getInductionVar(); - if (!loopNest.outerLoop) - loopNest.outerLoop = loopNest.innerLoop; + if (emitWorkshareLoop) { + auto wslw = builder.create(loc); + loopNest.outerOp = wslw; + builder.createBlock(&wslw.getRegion()); + mlir::omp::LoopNestOperands lnops; + lnops.loopInclusive = builder.getUnitAttr(); + for (auto extent : llvm::reverse(extents)) { + lnops.loopLowerBounds.push_back(one); + lnops.loopUpperBounds.push_back(extent); + lnops.loopSteps.push_back(one); + } + auto lnOp = builder.create(loc, lnops); + mlir::Block *block = builder.createBlock(&lnOp.getRegion()); + for (auto extent : llvm::reverse(extents)) + block->addArgument(extent.getType(), extent.getLoc()); + loopNest.body = block; + builder.create(loc); + for (unsigned dim = 0; dim < extents.size(); dim++) + loopNest.oneBasedIndices[extents.size() - dim - 1] = + lnOp.getRegion().front().getArgument(dim); + } else { + unsigned dim = extents.size() - 1; + for (auto extent : llvm::reverse(extents)) { + auto ub = builder.createConvert(loc, indexType, extent); + auto doLoop = + builder.create(loc, one, ub, one, isUnordered); + loopNest.body = doLoop.getBody(); + builder.setInsertionPointToStart(loopNest.body); + // Reverse the indices so they are in column-major order. + loopNest.oneBasedIndices[dim--] = doLoop.getInductionVar(); + if (!loopNest.outerOp) + loopNest.outerOp = doLoop; + } } - builder.restoreInsertionPoint(insPt); return loopNest; } diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 7c7c8ee539111db9755476b1e9977935b9fcb527..a2b327f45c6939af6666af780164977d3b5e57ce 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -97,7 +97,6 @@ static bool isStaticallyPresent(const fir::ExtendedValue &exv) { /// IEEE module procedure names not yet implemented for genModuleProcTODO. static constexpr char ieee_get_underflow_mode[] = "ieee_get_underflow_mode"; -static constexpr char ieee_rem[] = "ieee_rem"; static constexpr char ieee_set_underflow_mode[] = "ieee_set_underflow_mode"; using I = IntrinsicLibrary; @@ -362,7 +361,7 @@ static constexpr IntrinsicHandler handlers[]{ {"ieee_quiet_lt", &I::genIeeeQuietCompare}, {"ieee_quiet_ne", &I::genIeeeQuietCompare}, {"ieee_real", &I::genIeeeReal}, - {"ieee_rem", &I::genModuleProcTODO}, + {"ieee_rem", &I::genIeeeRem}, {"ieee_rint", &I::genIeeeRint}, {"ieee_round_eq", &I::genIeeeTypeCompare}, {"ieee_round_ne", &I::genIeeeTypeCompare}, @@ -1298,6 +1297,14 @@ static constexpr MathOperation mathOperations[] = { genFuncType, Ty::Complex<8>, Ty::Integer<8>>, genLibCall}, {"pow", RTNAME_STRING(cqpowk), FuncTypeComplex16Complex16Integer8, genLibF128Call}, + {"remainder", "remainderf", + genFuncType, Ty::Real<4>, Ty::Real<4>>, genLibCall}, + {"remainder", "remainder", + genFuncType, Ty::Real<8>, Ty::Real<8>>, genLibCall}, + {"remainder", "remainderl", + genFuncType, Ty::Real<10>, Ty::Real<10>>, genLibCall}, + {"remainder", RTNAME_STRING(RemainderF128), FuncTypeReal16Real16Real16, + genLibF128Call}, {"sign", "copysignf", genFuncType, Ty::Real<4>, Ty::Real<4>>, genMathOp}, {"sign", "copysign", genFuncType, Ty::Real<8>, Ty::Real<8>>, @@ -5030,6 +5037,32 @@ mlir::Value IntrinsicLibrary::genIeeeReal(mlir::Type resultType, return ifOp1.getResult(0); } +// IEEE_REM +mlir::Value IntrinsicLibrary::genIeeeRem(mlir::Type resultType, + llvm::ArrayRef args) { + // Return the remainder of X divided by Y. + // Signal IEEE_UNDERFLOW if X is subnormal and Y is infinite. + // Signal IEEE_INVALID if X is infinite or Y is zero and neither is a NaN. + assert(args.size() == 2); + mlir::Value x = args[0]; + mlir::Value y = args[1]; + if (mlir::dyn_cast(resultType).getWidth() < 32) { + mlir::Type f32Ty = mlir::FloatType::getF32(builder.getContext()); + x = builder.create(loc, f32Ty, x); + y = builder.create(loc, f32Ty, y); + } else { + x = builder.create(loc, resultType, x); + y = builder.create(loc, resultType, y); + } + // remainder calls do not signal IEEE_UNDERFLOW. + mlir::Value underflow = builder.create( + loc, genIsFPClass(builder.getI1Type(), x, subnormalTest), + genIsFPClass(builder.getI1Type(), y, infiniteTest)); + mlir::Value result = genRuntimeCall("remainder", x.getType(), {x, y}); + genRaiseExcept(_FORTRAN_RUNTIME_IEEE_UNDERFLOW, underflow); + return builder.create(loc, resultType, result); +} + // IEEE_RINT mlir::Value IntrinsicLibrary::genIeeeRint(mlir::Type resultType, llvm::ArrayRef args) { diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt index 646621cb01c157220617d4c87e33f5191cff537d..f47d11875f04db6abcb01eb5e4571f07dbe2cc78 100644 --- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt +++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt @@ -23,6 +23,7 @@ add_flang_library(FIRCodeGen FIRSupport MLIRComplexToLLVM MLIRComplexToStandard + MLIRGPUDialect MLIRMathToFuncs MLIRMathToLLVM MLIRMathToLibm diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index d038efcb2eb42c83a6eaca41ab4c0cf4f27612fe..2eeb182735094fc1e802581278e95ee0bd94257b 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -41,6 +41,7 @@ #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/DLTI/DLTI.h" +#include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/Transforms/AddComdats.h" @@ -278,7 +279,14 @@ struct AllocaOpConversion : public fir::FIROpConversion { mlir::Region *parentRegion = rewriter.getInsertionBlock()->getParent(); mlir::Block *insertBlock = getBlockForAllocaInsert(parentOp, parentRegion); - size.getDefiningOp()->moveBefore(&insertBlock->front()); + + // The old size might have had multiple users, some at a broader scope + // than we can safely outline the alloca to. As it is only an + // llvm.constant operation, it is faster to clone it than to calculate the + // dominance to see if it really should be moved. + mlir::Operation *clonedSize = rewriter.clone(*size.getDefiningOp()); + size = clonedSize->getResult(0); + clonedSize->moveBefore(&insertBlock->front()); rewriter.setInsertionPointAfter(size.getDefiningOp()); } @@ -920,17 +928,19 @@ struct EmboxCharOpConversion : public fir::FIROpConversion { }; } // namespace -/// Return the LLVMFuncOp corresponding to the standard malloc call. +template static mlir::SymbolRefAttr -getMalloc(fir::AllocMemOp op, mlir::ConversionPatternRewriter &rewriter) { +getMallocInModule(ModuleOp mod, fir::AllocMemOp op, + mlir::ConversionPatternRewriter &rewriter) { static constexpr char mallocName[] = "malloc"; - auto module = op->getParentOfType(); - if (auto mallocFunc = module.lookupSymbol(mallocName)) + if (auto mallocFunc = + mod.template lookupSymbol(mallocName)) return mlir::SymbolRefAttr::get(mallocFunc); - if (auto userMalloc = module.lookupSymbol(mallocName)) + if (auto userMalloc = + mod.template lookupSymbol(mallocName)) return mlir::SymbolRefAttr::get(userMalloc); - mlir::OpBuilder moduleBuilder( - op->getParentOfType().getBodyRegion()); + + mlir::OpBuilder moduleBuilder(mod.getBodyRegion()); auto indexType = mlir::IntegerType::get(op.getContext(), 64); auto mallocDecl = moduleBuilder.create( op.getLoc(), mallocName, @@ -940,6 +950,15 @@ getMalloc(fir::AllocMemOp op, mlir::ConversionPatternRewriter &rewriter) { return mlir::SymbolRefAttr::get(mallocDecl); } +/// Return the LLVMFuncOp corresponding to the standard malloc call. +static mlir::SymbolRefAttr +getMalloc(fir::AllocMemOp op, mlir::ConversionPatternRewriter &rewriter) { + if (auto mod = op->getParentOfType()) + return getMallocInModule(mod, op, rewriter); + auto mod = op->getParentOfType(); + return getMallocInModule(mod, op, rewriter); +} + /// Helper function for generating the LLVM IR that computes the distance /// in bytes between adjacent elements pointed to by a pointer /// of type \p ptrTy. The result is returned as a value of \p idxTy integer @@ -1016,18 +1035,20 @@ struct AllocMemOpConversion : public fir::FIROpConversion { } // namespace /// Return the LLVMFuncOp corresponding to the standard free call. -static mlir::SymbolRefAttr getFree(fir::FreeMemOp op, - mlir::ConversionPatternRewriter &rewriter) { +template +static mlir::SymbolRefAttr +getFreeInModule(ModuleOp mod, fir::FreeMemOp op, + mlir::ConversionPatternRewriter &rewriter) { static constexpr char freeName[] = "free"; - auto module = op->getParentOfType(); // Check if free already defined in the module. - if (auto freeFunc = module.lookupSymbol(freeName)) + if (auto freeFunc = + mod.template lookupSymbol(freeName)) return mlir::SymbolRefAttr::get(freeFunc); if (auto freeDefinedByUser = - module.lookupSymbol(freeName)) + mod.template lookupSymbol(freeName)) return mlir::SymbolRefAttr::get(freeDefinedByUser); // Create llvm declaration for free. - mlir::OpBuilder moduleBuilder(module.getBodyRegion()); + mlir::OpBuilder moduleBuilder(mod.getBodyRegion()); auto voidType = mlir::LLVM::LLVMVoidType::get(op.getContext()); auto freeDecl = moduleBuilder.create( rewriter.getUnknownLoc(), freeName, @@ -1037,6 +1058,14 @@ static mlir::SymbolRefAttr getFree(fir::FreeMemOp op, return mlir::SymbolRefAttr::get(freeDecl); } +static mlir::SymbolRefAttr getFree(fir::FreeMemOp op, + mlir::ConversionPatternRewriter &rewriter) { + if (auto mod = op->getParentOfType()) + return getFreeInModule(mod, op, rewriter); + auto mod = op->getParentOfType(); + return getFreeInModule(mod, op, rewriter); +} + static unsigned getDimension(mlir::LLVM::LLVMArrayType ty) { unsigned result = 1; for (auto eleTy = @@ -3730,6 +3759,7 @@ public: mlir::configureOpenMPToLLVMConversionLegality(target, typeConverter); target.addLegalDialect(); target.addLegalDialect(); + target.addLegalDialect(); // required NOPs for applying a full conversion target.addLegalOp(); diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp index 6c148dffb0e55a2538901dad71e8858ef47859a7..9ec055b1aecabbcc5dfba61755271edc22471d21 100644 --- a/flang/lib/Optimizer/CodeGen/Target.cpp +++ b/flang/lib/Optimizer/CodeGen/Target.cpp @@ -1091,6 +1091,13 @@ struct TargetLoongArch64 : public GenericTarget { // Two distinct element type arguments (re, im) marshal.emplace_back(eleTy, AT{}); marshal.emplace_back(eleTy, AT{}); + } else if (sem == &llvm::APFloat::IEEEquad()) { + // Use a type that will be translated into LLVM as: + // { fp128, fp128 } struct of 2 fp128, byval + marshal.emplace_back( + fir::ReferenceType::get(mlir::TupleType::get( + eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), + AT{/*align=*/16, /*byval=*/true}); } else { typeTodo(sem, loc, "argument"); } @@ -1108,11 +1115,42 @@ struct TargetLoongArch64 : public GenericTarget { marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy}), AT{/*alignment=*/0, /*byval=*/true}); + } else if (sem == &llvm::APFloat::IEEEquad()) { + // Use a type that will be translated into LLVM as: + // { fp128, fp128 } struct of 2 fp128, sret, align 16 + marshal.emplace_back( + fir::ReferenceType::get(mlir::TupleType::get( + eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), + AT{/*align=*/16, /*byval=*/false, /*sret=*/true}); } else { typeTodo(sem, loc, "return"); } return marshal; } + + CodeGenSpecifics::Marshalling + integerArgumentType(mlir::Location loc, + mlir::IntegerType argTy) const override { + if (argTy.getWidth() == 32) { + // LA64 LP64D ABI requires unsigned 32 bit integers to be sign extended. + // Therefore, Flang also follows it if a function needs to be + // interoperable with C. + // + // Currently, it only adds `signext` attribute to the dummy arguments and + // return values in the function signatures, but it does not add the + // corresponding attribute to the actual arguments and return values in + // `fir.call` instruction. Thanks to LLVM's integration of all these + // attributes, the modification is still effective. + CodeGenSpecifics::Marshalling marshal; + AT::IntegerExtension intExt = AT::IntegerExtension::Sign; + marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false, + /*sret=*/false, /*append=*/false, + /*intExt=*/intExt}); + return marshal; + } + + return GenericTarget::integerArgumentType(loc, argTy); + } }; } // namespace diff --git a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp index 0b03e070a0076e8c5d6ef10618bf2a9b693f492e..b05991a29a32132887876a5ecf4cc45f4a46ba21 100644 --- a/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp +++ b/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp @@ -102,7 +102,7 @@ llvm::LogicalResult cuf::DataTransferOp::verify() { mlir::Type srcTy = getSrc().getType(); mlir::Type dstTy = getDst().getType(); if (getShape()) { - if (!fir::isa_ref_type(srcTy) || !fir::isa_ref_type(dstTy)) + if (!fir::isa_ref_type(srcTy) && !fir::isa_ref_type(dstTy)) return emitOpError() << "shape can only be specified on data transfer with references"; } diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp index a70a6b388c4b1aea83373418b5726244713ff4fc..1848dbe2c7a2c23af39cdd111e93ecbab9f1b192 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp @@ -26,6 +26,8 @@ #include "flang/Optimizer/HLFIR/HLFIRDialect.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Optimizer/HLFIR/Passes.h" +#include "flang/Optimizer/OpenMP/Passes.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/Dominance.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Pass/Pass.h" @@ -791,9 +793,10 @@ struct ElementalOpConversion // Generate a loop nest looping around the fir.elemental shape and clone // fir.elemental region inside the inner loop. hlfir::LoopNest loopNest = - hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered()); + hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered(), + flangomp::shouldUseWorkshareLowering(elemental)); auto insPt = builder.saveInsertionPoint(); - builder.setInsertionPointToStart(loopNest.innerLoop.getBody()); + builder.setInsertionPointToStart(loopNest.body); auto yield = hlfir::inlineElementalOp(loc, builder, elemental, loopNest.oneBasedIndices); hlfir::Entity elementValue(yield.getElementValue()); diff --git a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt index fa3a59303137ffdeea2a66fad3e792b9307cadb0..d18df2ef49f10ee0502bc1dfe67ae996ec33f42f 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt @@ -24,6 +24,7 @@ add_flang_library(HLFIRTransforms FIRDialectSupport FIRSupport FIRTransforms + FlangOpenMPTransforms HLFIRDialect MLIRIR ${dialect_libs} diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp index 85dd517cb57914298fcabd180c67d05ca15cabe7..424566462e8fe020541653eccf69dc5c9b0f3070 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp @@ -464,7 +464,7 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) { // if the LHS is not). mlir::Value shape = hlfir::genShape(loc, builder, lhsEntity); elementalLoopNest = hlfir::genLoopNest(loc, builder, shape); - builder.setInsertionPointToStart(elementalLoopNest->innerLoop.getBody()); + builder.setInsertionPointToStart(elementalLoopNest->body); lhsEntity = hlfir::getElementAt(loc, builder, lhsEntity, elementalLoopNest->oneBasedIndices); rhsEntity = hlfir::getElementAt(loc, builder, rhsEntity, @@ -484,7 +484,7 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) { for (auto &cleanupConversion : argConversionCleanups) cleanupConversion(); if (elementalLoopNest) - builder.setInsertionPointAfter(elementalLoopNest->outerLoop); + builder.setInsertionPointAfter(elementalLoopNest->outerOp); } else { // TODO: preserve allocatable assignment aspects for forall once // they are conveyed in hlfir.region_assign. @@ -492,8 +492,7 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) { } generateCleanupIfAny(loweredLhs.elementalCleanup); if (loweredLhs.vectorSubscriptLoopNest) - builder.setInsertionPointAfter( - loweredLhs.vectorSubscriptLoopNest->outerLoop); + builder.setInsertionPointAfter(loweredLhs.vectorSubscriptLoopNest->outerOp); generateCleanupIfAny(oldRhsYield); generateCleanupIfAny(loweredLhs.nonElementalCleanup); } @@ -518,8 +517,8 @@ void OrderedAssignmentRewriter::pre(hlfir::WhereOp whereOp) { hlfir::Entity savedMask{maybeSaved->first}; mlir::Value shape = hlfir::genShape(loc, builder, savedMask); whereLoopNest = hlfir::genLoopNest(loc, builder, shape); - constructStack.push_back(whereLoopNest->outerLoop.getOperation()); - builder.setInsertionPointToStart(whereLoopNest->innerLoop.getBody()); + constructStack.push_back(whereLoopNest->outerOp); + builder.setInsertionPointToStart(whereLoopNest->body); mlir::Value cdt = hlfir::getElementAt(loc, builder, savedMask, whereLoopNest->oneBasedIndices); generateMaskIfOp(cdt); @@ -527,7 +526,7 @@ void OrderedAssignmentRewriter::pre(hlfir::WhereOp whereOp) { // If this is the same run as the one that saved the value, the clean-up // was left-over to be done now. auto insertionPoint = builder.saveInsertionPoint(); - builder.setInsertionPointAfter(whereLoopNest->outerLoop); + builder.setInsertionPointAfter(whereLoopNest->outerOp); generateCleanupIfAny(maybeSaved->second); builder.restoreInsertionPoint(insertionPoint); } @@ -539,8 +538,8 @@ void OrderedAssignmentRewriter::pre(hlfir::WhereOp whereOp) { mask.generateNoneElementalPart(builder, mapper); mlir::Value shape = mask.generateShape(builder, mapper); whereLoopNest = hlfir::genLoopNest(loc, builder, shape); - constructStack.push_back(whereLoopNest->outerLoop.getOperation()); - builder.setInsertionPointToStart(whereLoopNest->innerLoop.getBody()); + constructStack.push_back(whereLoopNest->outerOp); + builder.setInsertionPointToStart(whereLoopNest->body); mlir::Value cdt = generateMaskedEntity(mask); generateMaskIfOp(cdt); return; @@ -754,7 +753,7 @@ OrderedAssignmentRewriter::generateYieldedLHS( loweredLhs.vectorSubscriptLoopNest = hlfir::genLoopNest( loc, builder, loweredLhs.vectorSubscriptShape.value()); builder.setInsertionPointToStart( - loweredLhs.vectorSubscriptLoopNest->innerLoop.getBody()); + loweredLhs.vectorSubscriptLoopNest->body); } loweredLhs.lhs = temp->second.fetch(loc, builder); return loweredLhs; @@ -771,8 +770,7 @@ OrderedAssignmentRewriter::generateYieldedLHS( loweredLhs.vectorSubscriptLoopNest = hlfir::genLoopNest(loc, builder, *loweredLhs.vectorSubscriptShape, !elementalAddrLhs.isOrdered()); - builder.setInsertionPointToStart( - loweredLhs.vectorSubscriptLoopNest->innerLoop.getBody()); + builder.setInsertionPointToStart(loweredLhs.vectorSubscriptLoopNest->body); mapper.map(elementalAddrLhs.getIndices(), loweredLhs.vectorSubscriptLoopNest->oneBasedIndices); for (auto &op : elementalAddrLhs.getBody().front().without_terminator()) @@ -798,11 +796,11 @@ OrderedAssignmentRewriter::generateMaskedEntity(MaskedArrayExpr &maskedExpr) { if (!maskedExpr.noneElementalPartWasGenerated) { // Generate none elemental part before the where loops (but inside the // current forall loops if any). - builder.setInsertionPoint(whereLoopNest->outerLoop); + builder.setInsertionPoint(whereLoopNest->outerOp); maskedExpr.generateNoneElementalPart(builder, mapper); } // Generate the none elemental part cleanup after the where loops. - builder.setInsertionPointAfter(whereLoopNest->outerLoop); + builder.setInsertionPointAfter(whereLoopNest->outerOp); maskedExpr.generateNoneElementalCleanupIfAny(builder, mapper); // Generate the value of the current element for the masked expression // at the current insertion point (inside the where loops, and any fir.if @@ -1242,7 +1240,7 @@ void OrderedAssignmentRewriter::saveLeftHandSide( LhsValueAndCleanUp loweredLhs = generateYieldedLHS(loc, region); fir::factory::TemporaryStorage *temp = nullptr; if (loweredLhs.vectorSubscriptLoopNest) - constructStack.push_back(loweredLhs.vectorSubscriptLoopNest->outerLoop); + constructStack.push_back(loweredLhs.vectorSubscriptLoopNest->outerOp); if (loweredLhs.vectorSubscriptLoopNest && !rhsIsArray(regionAssignOp)) { // Vector subscripted entity for which the shape must also be saved on top // of the element addresses (e.g. the shape may change in each forall @@ -1265,7 +1263,7 @@ void OrderedAssignmentRewriter::saveLeftHandSide( // subscripted LHS. auto &vectorTmp = temp->cast(); auto insertionPoint = builder.saveInsertionPoint(); - builder.setInsertionPoint(loweredLhs.vectorSubscriptLoopNest->outerLoop); + builder.setInsertionPoint(loweredLhs.vectorSubscriptLoopNest->outerOp); vectorTmp.pushShape(loc, builder, shape); builder.restoreInsertionPoint(insertionPoint); } else { @@ -1290,8 +1288,7 @@ void OrderedAssignmentRewriter::saveLeftHandSide( generateCleanupIfAny(loweredLhs.elementalCleanup); if (loweredLhs.vectorSubscriptLoopNest) { constructStack.pop_back(); - builder.setInsertionPointAfter( - loweredLhs.vectorSubscriptLoopNest->outerLoop); + builder.setInsertionPointAfter(loweredLhs.vectorSubscriptLoopNest->outerOp); } } diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp index d05a3258cf293c0e5e9a329d4fd6b9516e99f510..a0160b233e3cd1af96a29fda03a61518fb2806ee 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp @@ -20,6 +20,7 @@ #include "flang/Optimizer/HLFIR/HLFIRDialect.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Optimizer/HLFIR/Passes.h" +#include "flang/Optimizer/OpenMP/Passes.h" #include "flang/Optimizer/Transforms/Utils.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Dominance.h" @@ -482,8 +483,9 @@ llvm::LogicalResult ElementalAssignBufferization::matchAndRewrite( // Generate a loop nest looping around the hlfir.elemental shape and clone // hlfir.elemental region inside the inner loop hlfir::LoopNest loopNest = - hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered()); - builder.setInsertionPointToStart(loopNest.innerLoop.getBody()); + hlfir::genLoopNest(loc, builder, extents, !elemental.isOrdered(), + flangomp::shouldUseWorkshareLowering(elemental)); + builder.setInsertionPointToStart(loopNest.body); auto yield = hlfir::inlineElementalOp(loc, builder, elemental, loopNest.oneBasedIndices); hlfir::Entity elementValue{yield.getElementValue()}; @@ -553,8 +555,9 @@ llvm::LogicalResult BroadcastAssignBufferization::matchAndRewrite( llvm::SmallVector extents = hlfir::getIndexExtents(loc, builder, shape); hlfir::LoopNest loopNest = - hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true); - builder.setInsertionPointToStart(loopNest.innerLoop.getBody()); + hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true, + flangomp::shouldUseWorkshareLowering(assign)); + builder.setInsertionPointToStart(loopNest.body); auto arrayElement = hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices); builder.create(loc, rhs, arrayElement); @@ -651,8 +654,9 @@ llvm::LogicalResult VariableAssignBufferization::matchAndRewrite( llvm::SmallVector extents = hlfir::getIndexExtents(loc, builder, shape); hlfir::LoopNest loopNest = - hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true); - builder.setInsertionPointToStart(loopNest.innerLoop.getBody()); + hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true, + flangomp::shouldUseWorkshareLowering(assign)); + builder.setInsertionPointToStart(loopNest.body); auto rhsArrayElement = hlfir::getElementAt(loc, builder, rhs, loopNest.oneBasedIndices); rhsArrayElement = hlfir::loadTrivialScalar(loc, builder, rhsArrayElement); diff --git a/flang/lib/Optimizer/OpenMP/CMakeLists.txt b/flang/lib/Optimizer/OpenMP/CMakeLists.txt index 035d0d5ca46c76dca1371804df3b04d726a9462a..b1e0dbf6e707e55de64045baec2a05901296cd08 100644 --- a/flang/lib/Optimizer/OpenMP/CMakeLists.txt +++ b/flang/lib/Optimizer/OpenMP/CMakeLists.txt @@ -5,6 +5,7 @@ add_flang_library(FlangOpenMPTransforms MapsForPrivatizedSymbols.cpp MapInfoFinalization.cpp MarkDeclareTarget.cpp + LowerWorkshare.cpp DEPENDS FIRDialect diff --git a/flang/lib/Optimizer/OpenMP/LowerWorkshare.cpp b/flang/lib/Optimizer/OpenMP/LowerWorkshare.cpp new file mode 100644 index 0000000000000000000000000000000000000000..225c585a02d913d8fb11c41ef47eed4e3fbaaa95 --- /dev/null +++ b/flang/lib/Optimizer/OpenMP/LowerWorkshare.cpp @@ -0,0 +1,527 @@ +//===- LowerWorkshare.cpp - special cases for bufferization -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the lowering of omp.workshare to other omp constructs. +// +// This pass is tasked with parallelizing the loops nested in +// workshare.loop_wrapper while both the Fortran to mlir lowering and the hlfir +// to fir lowering pipelines are responsible for emitting the +// workshare.loop_wrapper ops where appropriate according to the +// `shouldUseWorkshareLowering` function. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace flangomp { +#define GEN_PASS_DEF_LOWERWORKSHARE +#include "flang/Optimizer/OpenMP/Passes.h.inc" +} // namespace flangomp + +#define DEBUG_TYPE "lower-workshare" + +using namespace mlir; + +namespace flangomp { + +// Checks for nesting pattern below as we need to avoid sharing the work of +// statements which are nested in some constructs such as omp.critical or +// another omp.parallel. +// +// omp.workshare { // `wsOp` +// ... +// omp.T { // `parent` +// ... +// `op` +// +template +static bool isNestedIn(omp::WorkshareOp wsOp, Operation *op) { + T parent = op->getParentOfType(); + if (!parent) + return false; + return wsOp->isProperAncestor(parent); +} + +bool shouldUseWorkshareLowering(Operation *op) { + auto parentWorkshare = op->getParentOfType(); + + if (!parentWorkshare) + return false; + + if (isNestedIn(parentWorkshare, op)) + return false; + + // 2.8.3 workshare Construct + // For a parallel construct, the construct is a unit of work with respect to + // the workshare construct. The statements contained in the parallel construct + // are executed by a new thread team. + if (isNestedIn(parentWorkshare, op)) + return false; + + // 2.8.2 single Construct + // Binding The binding thread set for a single region is the current team. A + // single region binds to the innermost enclosing parallel region. + // Description Only one of the encountering threads will execute the + // structured block associated with the single construct. + if (isNestedIn(parentWorkshare, op)) + return false; + + // Do not use workshare lowering until we support CFG in omp.workshare + if (parentWorkshare.getRegion().getBlocks().size() != 1) + return false; + + return true; +} + +} // namespace flangomp + +namespace { + +struct SingleRegion { + Block::iterator begin, end; +}; + +static bool mustParallelizeOp(Operation *op) { + return op + ->walk([&](Operation *nested) { + // We need to be careful not to pick up workshare.loop_wrapper in nested + // omp.parallel{omp.workshare} regions, i.e. make sure that `nested` + // binds to the workshare region we are currently handling. + // + // For example: + // + // omp.parallel { + // omp.workshare { // currently handling this + // omp.parallel { + // omp.workshare { // nested workshare + // omp.workshare.loop_wrapper {} + // + // Therefore, we skip if we encounter a nested omp.workshare. + if (isa(op)) + return WalkResult::skip(); + if (isa(op)) + return WalkResult::interrupt(); + return WalkResult::advance(); + }) + .wasInterrupted(); +} + +static bool isSafeToParallelize(Operation *op) { + return isa(op) || isa(op) || + isMemoryEffectFree(op); +} + +/// Simple shallow copies suffice for our purposes in this pass, so we implement +/// this simpler alternative to the full fledged `createCopyFunc` in the +/// frontend +static mlir::func::FuncOp createCopyFunc(mlir::Location loc, mlir::Type varType, + fir::FirOpBuilder builder) { + mlir::ModuleOp module = builder.getModule(); + auto rt = cast(varType); + mlir::Type eleTy = rt.getEleTy(); + std::string copyFuncName = + fir::getTypeAsString(eleTy, builder.getKindMap(), "_workshare_copy"); + + if (auto decl = module.lookupSymbol(copyFuncName)) + return decl; + // create function + mlir::OpBuilder::InsertionGuard guard(builder); + mlir::OpBuilder modBuilder(module.getBodyRegion()); + llvm::SmallVector argsTy = {varType, varType}; + auto funcType = mlir::FunctionType::get(builder.getContext(), argsTy, {}); + mlir::func::FuncOp funcOp = + modBuilder.create(loc, copyFuncName, funcType); + funcOp.setVisibility(mlir::SymbolTable::Visibility::Private); + builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy, + {loc, loc}); + builder.setInsertionPointToStart(&funcOp.getRegion().back()); + + Value loaded = builder.create(loc, funcOp.getArgument(1)); + builder.create(loc, loaded, funcOp.getArgument(0)); + + builder.create(loc); + return funcOp; +} + +static bool isUserOutsideSR(Operation *user, Operation *parentOp, + SingleRegion sr) { + while (user->getParentOp() != parentOp) + user = user->getParentOp(); + return sr.begin->getBlock() != user->getBlock() || + !(user->isBeforeInBlock(&*sr.end) && sr.begin->isBeforeInBlock(user)); +} + +static bool isTransitivelyUsedOutside(Value v, SingleRegion sr) { + Block *srBlock = sr.begin->getBlock(); + Operation *parentOp = srBlock->getParentOp(); + + for (auto &use : v.getUses()) { + Operation *user = use.getOwner(); + if (isUserOutsideSR(user, parentOp, sr)) + return true; + + // Now we know user is inside `sr`. + + // Results of nested users cannot be used outside of `sr`. + if (user->getBlock() != srBlock) + continue; + + // A non-safe to parallelize operation will be checked for uses outside + // separately. + if (!isSafeToParallelize(user)) + continue; + + // For safe to parallelize operations, we need to check if there is a + // transitive use of `v` through them. + for (auto res : user->getResults()) + if (isTransitivelyUsedOutside(res, sr)) + return true; + } + return false; +} + +/// We clone pure operations in both the parallel and single blocks. this +/// functions cleans them up if they end up with no uses +static void cleanupBlock(Block *block) { + for (Operation &op : llvm::make_early_inc_range( + llvm::make_range(block->rbegin(), block->rend()))) + if (isOpTriviallyDead(&op)) + op.erase(); +} + +static void parallelizeRegion(Region &sourceRegion, Region &targetRegion, + IRMapping &rootMapping, Location loc, + mlir::DominanceInfo &di) { + OpBuilder rootBuilder(sourceRegion.getContext()); + ModuleOp m = sourceRegion.getParentOfType(); + OpBuilder copyFuncBuilder(m.getBodyRegion()); + fir::FirOpBuilder firCopyFuncBuilder(copyFuncBuilder, m); + + auto mapReloadedValue = + [&](Value v, OpBuilder allocaBuilder, OpBuilder singleBuilder, + OpBuilder parallelBuilder, IRMapping singleMapping) -> Value { + if (auto reloaded = rootMapping.lookupOrNull(v)) + return nullptr; + Type ty = v.getType(); + Value alloc = allocaBuilder.create(loc, ty); + singleBuilder.create(loc, singleMapping.lookup(v), alloc); + Value reloaded = parallelBuilder.create(loc, ty, alloc); + rootMapping.map(v, reloaded); + return alloc; + }; + + auto moveToSingle = + [&](SingleRegion sr, OpBuilder allocaBuilder, OpBuilder singleBuilder, + OpBuilder parallelBuilder) -> std::pair> { + IRMapping singleMapping = rootMapping; + SmallVector copyPrivate; + bool allParallelized = true; + + for (Operation &op : llvm::make_range(sr.begin, sr.end)) { + if (isSafeToParallelize(&op)) { + singleBuilder.clone(op, singleMapping); + if (llvm::all_of(op.getOperands(), [&](Value opr) { + // Either we have already remapped it + bool remapped = rootMapping.contains(opr); + // Or it is available because it dominates `sr` + bool dominates = + di.properlyDominates(opr.getDefiningOp(), &*sr.begin); + return remapped || dominates; + })) { + // Safe to parallelize operations which have all operands available in + // the root parallel block can be executed there. + parallelBuilder.clone(op, rootMapping); + } else { + // If any operand was not available, it means that there was no + // transitive use of a non-safe-to-parallelize operation outside `sr`. + // This means that there should be no transitive uses outside `sr` of + // `op`. + assert(llvm::all_of(op.getResults(), [&](Value v) { + return !isTransitivelyUsedOutside(v, sr); + })); + allParallelized = false; + } + } else if (auto alloca = dyn_cast(&op)) { + auto hoisted = + cast(allocaBuilder.clone(*alloca, singleMapping)); + rootMapping.map(&*alloca, &*hoisted); + rootMapping.map(alloca.getResult(), hoisted.getResult()); + copyPrivate.push_back(hoisted); + allParallelized = false; + } else { + singleBuilder.clone(op, singleMapping); + // Prepare reloaded values for results of operations that cannot be + // safely parallelized and which are used after the region `sr`. + for (auto res : op.getResults()) { + if (isTransitivelyUsedOutside(res, sr)) { + auto alloc = mapReloadedValue(res, allocaBuilder, singleBuilder, + parallelBuilder, singleMapping); + if (alloc) + copyPrivate.push_back(alloc); + } + } + allParallelized = false; + } + } + singleBuilder.create(loc); + return {allParallelized, copyPrivate}; + }; + + for (Block &block : sourceRegion) { + Block *targetBlock = rootBuilder.createBlock( + &targetRegion, {}, block.getArgumentTypes(), + llvm::map_to_vector(block.getArguments(), + [](BlockArgument arg) { return arg.getLoc(); })); + rootMapping.map(&block, targetBlock); + rootMapping.map(block.getArguments(), targetBlock->getArguments()); + } + + auto handleOneBlock = [&](Block &block) { + Block &targetBlock = *rootMapping.lookup(&block); + rootBuilder.setInsertionPointToStart(&targetBlock); + Operation *terminator = block.getTerminator(); + SmallVector> regions; + + auto it = block.begin(); + auto getOneRegion = [&]() { + if (&*it == terminator) + return false; + if (mustParallelizeOp(&*it)) { + regions.push_back(&*it); + it++; + return true; + } + SingleRegion sr; + sr.begin = it; + while (&*it != terminator && !mustParallelizeOp(&*it)) + it++; + sr.end = it; + assert(sr.begin != sr.end); + regions.push_back(sr); + return true; + }; + while (getOneRegion()) + ; + + for (auto [i, opOrSingle] : llvm::enumerate(regions)) { + bool isLast = i + 1 == regions.size(); + if (std::holds_alternative(opOrSingle)) { + OpBuilder singleBuilder(sourceRegion.getContext()); + Block *singleBlock = new Block(); + singleBuilder.setInsertionPointToStart(singleBlock); + + OpBuilder allocaBuilder(sourceRegion.getContext()); + Block *allocaBlock = new Block(); + allocaBuilder.setInsertionPointToStart(allocaBlock); + + OpBuilder parallelBuilder(sourceRegion.getContext()); + Block *parallelBlock = new Block(); + parallelBuilder.setInsertionPointToStart(parallelBlock); + + auto [allParallelized, copyprivateVars] = + moveToSingle(std::get(opOrSingle), allocaBuilder, + singleBuilder, parallelBuilder); + if (allParallelized) { + // The single region was not required as all operations were safe to + // parallelize + assert(copyprivateVars.empty()); + assert(allocaBlock->empty()); + delete singleBlock; + } else { + omp::SingleOperands singleOperands; + if (isLast) + singleOperands.nowait = rootBuilder.getUnitAttr(); + singleOperands.copyprivateVars = copyprivateVars; + cleanupBlock(singleBlock); + for (auto var : singleOperands.copyprivateVars) { + mlir::func::FuncOp funcOp = + createCopyFunc(loc, var.getType(), firCopyFuncBuilder); + singleOperands.copyprivateSyms.push_back( + SymbolRefAttr::get(funcOp)); + } + omp::SingleOp singleOp = + rootBuilder.create(loc, singleOperands); + singleOp.getRegion().push_back(singleBlock); + targetRegion.front().getOperations().splice( + singleOp->getIterator(), allocaBlock->getOperations()); + } + rootBuilder.getInsertionBlock()->getOperations().splice( + rootBuilder.getInsertionPoint(), parallelBlock->getOperations()); + delete allocaBlock; + delete parallelBlock; + } else { + auto op = std::get(opOrSingle); + if (auto wslw = dyn_cast(op)) { + omp::WsloopOperands wsloopOperands; + if (isLast) + wsloopOperands.nowait = rootBuilder.getUnitAttr(); + auto wsloop = + rootBuilder.create(loc, wsloopOperands); + auto clonedWslw = cast( + rootBuilder.clone(*wslw, rootMapping)); + wsloop.getRegion().takeBody(clonedWslw.getRegion()); + clonedWslw->erase(); + } else { + assert(mustParallelizeOp(op)); + Operation *cloned = rootBuilder.cloneWithoutRegions(*op, rootMapping); + for (auto [region, clonedRegion] : + llvm::zip(op->getRegions(), cloned->getRegions())) + parallelizeRegion(region, clonedRegion, rootMapping, loc, di); + } + } + } + + rootBuilder.clone(*block.getTerminator(), rootMapping); + }; + + if (sourceRegion.hasOneBlock()) { + handleOneBlock(sourceRegion.front()); + } else { + auto &domTree = di.getDomTree(&sourceRegion); + for (auto node : llvm::breadth_first(domTree.getRootNode())) { + handleOneBlock(*node->getBlock()); + } + } + + for (Block &targetBlock : targetRegion) + cleanupBlock(&targetBlock); +} + +/// Lowers workshare to a sequence of single-thread regions and parallel loops +/// +/// For example: +/// +/// omp.workshare { +/// %a = fir.allocmem +/// omp.workshare.loop_wrapper {} +/// fir.call Assign %b %a +/// fir.freemem %a +/// } +/// +/// becomes +/// +/// %tmp = fir.alloca +/// omp.single copyprivate(%tmp) { +/// %a = fir.allocmem +/// fir.store %a %tmp +/// } +/// %a_reloaded = fir.load %tmp +/// omp.workshare.loop_wrapper {} +/// omp.single { +/// fir.call Assign %b %a_reloaded +/// fir.freemem %a_reloaded +/// } +/// +/// Note that we allocate temporary memory for values in omp.single's which need +/// to be accessed by all threads and broadcast them using single's copyprivate +LogicalResult lowerWorkshare(mlir::omp::WorkshareOp wsOp, DominanceInfo &di) { + Location loc = wsOp->getLoc(); + IRMapping rootMapping; + + OpBuilder rootBuilder(wsOp); + + // FIXME Currently, we only support workshare constructs with structured + // control flow. The transformation itself supports CFG, however, once we + // transform the MLIR region in the omp.workshare, we need to inline that + // region in the parent block. We have no guarantees at this point of the + // pipeline that the parent op supports CFG (e.g. fir.if), thus this is not + // generally possible. The alternative is to put the lowered region in an + // operation akin to scf.execute_region, which will get lowered at the same + // time when fir ops get lowered to CFG. However, SCF is not registered in + // flang so we cannot use it. Remove this requirement once we have + // scf.execute_region or an alternative operation available. + if (wsOp.getRegion().getBlocks().size() == 1) { + // This operation is just a placeholder which will be erased later. We need + // it because our `parallelizeRegion` function works on regions and not + // blocks. + omp::WorkshareOp newOp = + rootBuilder.create(loc, omp::WorkshareOperands()); + if (!wsOp.getNowait()) + rootBuilder.create(loc); + + parallelizeRegion(wsOp.getRegion(), newOp.getRegion(), rootMapping, loc, + di); + + // Inline the contents of the placeholder workshare op into its parent + // block. + Block *theBlock = &newOp.getRegion().front(); + Operation *term = theBlock->getTerminator(); + Block *parentBlock = wsOp->getBlock(); + parentBlock->getOperations().splice(newOp->getIterator(), + theBlock->getOperations()); + assert(term->getNumOperands() == 0); + term->erase(); + newOp->erase(); + wsOp->erase(); + } else { + // Otherwise just change the operation to an omp.single. + + wsOp->emitWarning( + "omp workshare with unstructured control flow is currently " + "unsupported and will be serialized."); + + // `shouldUseWorkshareLowering` should have guaranteed that there are no + // omp.workshare_loop_wrapper's that bind to this omp.workshare. + assert(!wsOp->walk([&](Operation *op) { + // Nested omp.workshare can have their own + // omp.workshare_loop_wrapper's. + if (isa(op)) + return WalkResult::skip(); + if (isa(op)) + return WalkResult::interrupt(); + return WalkResult::advance(); + }) + .wasInterrupted()); + + omp::SingleOperands operands; + operands.nowait = wsOp.getNowaitAttr(); + omp::SingleOp newOp = rootBuilder.create(loc, operands); + + newOp.getRegion().getBlocks().splice(newOp.getRegion().getBlocks().begin(), + wsOp.getRegion().getBlocks()); + wsOp->erase(); + } + return success(); +} + +class LowerWorksharePass + : public flangomp::impl::LowerWorkshareBase { +public: + void runOnOperation() override { + mlir::DominanceInfo &di = getAnalysis(); + getOperation()->walk([&](mlir::omp::WorkshareOp wsOp) { + if (failed(lowerWorkshare(wsOp, di))) + signalPassFailure(); + }); + } +}; +} // namespace diff --git a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp index 7ebeb51cf3dec758ced4134ee9b88fa88f4ba21d..4575c90e34acdd216402b4a73e84cea55ccb6243 100644 --- a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp +++ b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp @@ -38,7 +38,10 @@ #include "mlir/Support/LLVM.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" +#include +#include #include +#include namespace flangomp { #define GEN_PASS_DEF_MAPINFOFINALIZATIONPASS @@ -49,6 +52,12 @@ namespace { class MapInfoFinalizationPass : public flangomp::impl::MapInfoFinalizationPassBase< MapInfoFinalizationPass> { + /// Helper class tracking a members parent and its + /// placement in the parents member list + struct ParentAndPlacement { + mlir::omp::MapInfoOp parent; + size_t index; + }; /// Tracks any intermediate function/subroutine local allocations we /// generate for the descriptors of box type dummy arguments, so that @@ -58,21 +67,66 @@ class MapInfoFinalizationPass /*corresponding local alloca=*/fir::AllocaOp> localBoxAllocas; - void genDescriptorMemberMaps(mlir::omp::MapInfoOp op, - fir::FirOpBuilder &builder, - mlir::Operation *target) { - mlir::Location loc = op.getLoc(); - mlir::Value descriptor = op.getVarPtr(); + /// getMemberUserList gathers all users of a particular MapInfoOp that are + /// other MapInfoOp's and places them into the mapMemberUsers list, which + /// records the map that the current argument MapInfoOp "op" is part of + /// alongside the placement of "op" in the recorded users members list. The + /// intent of the generated list is to find all MapInfoOp's that may be + /// considered parents of the passed in "op" and in which it shows up in the + /// member list, alongside collecting the placement information of "op" in its + /// parents member list. + void + getMemberUserList(mlir::omp::MapInfoOp op, + llvm::SmallVectorImpl &mapMemberUsers) { + for (auto *user : op->getUsers()) + if (auto map = mlir::dyn_cast_if_present(user)) + for (auto [i, mapMember] : llvm::enumerate(map.getMembers())) + if (mapMember.getDefiningOp() == op) + mapMemberUsers.push_back({map, i}); + } + + void getAsIntegers(llvm::ArrayRef values, + llvm::SmallVectorImpl &ints) { + ints.reserve(values.size()); + llvm::transform(values, std::back_inserter(ints), + [](mlir::Attribute value) { + return mlir::cast(value).getInt(); + }); + } + + /// This function will expand a MapInfoOp's member indices back into a vector + /// so that they can be trivially modified as unfortunately the attribute type + /// that's used does not have modifiable fields at the moment (generally + /// awkward to work with) + void getMemberIndicesAsVectors( + mlir::omp::MapInfoOp mapInfo, + llvm::SmallVectorImpl> &indices) { + indices.reserve(mapInfo.getMembersIndexAttr().getValue().size()); + llvm::transform(mapInfo.getMembersIndexAttr().getValue(), + std::back_inserter(indices), [this](mlir::Attribute value) { + auto memberIndex = mlir::cast(value); + llvm::SmallVector indexes; + getAsIntegers(memberIndex.getValue(), indexes); + return indexes; + }); + } - // If we enter this function, but the mapped type itself is not the - // descriptor, then it's likely the address of the descriptor so we - // must retrieve the descriptor SSA. - if (!fir::isTypeWithDescriptor(op.getVarType())) { + /// When provided a MapInfoOp containing a descriptor type that + /// we must expand into multiple maps this function will extract + /// the value from it and return it, in certain cases we must + /// generate a new allocation to store into so that the + /// fir::BoxOffsetOp we utilise to access the descriptor datas + /// base address can be utilised. + mlir::Value getDescriptorFromBoxMap(mlir::omp::MapInfoOp boxMap, + fir::FirOpBuilder &builder) { + mlir::Value descriptor = boxMap.getVarPtr(); + if (!fir::isTypeWithDescriptor(boxMap.getVarType())) if (auto addrOp = mlir::dyn_cast_if_present( - op.getVarPtr().getDefiningOp())) { + boxMap.getVarPtr().getDefiningOp())) descriptor = addrOp.getVal(); - } - } + + if (!mlir::isa(descriptor.getType())) + return descriptor; // The fir::BoxOffsetOp only works with !fir.ref> types, as // allowing it to access non-reference box operations can cause some @@ -81,105 +135,188 @@ class MapInfoFinalizationPass // !fir.ref> to access the data we need to map we must // perform an alloca and then store to it and retrieve the data from the new // alloca. - if (mlir::isa(descriptor.getType())) { - // If we have already created a local allocation for this BoxType, - // we must be sure to re-use it so that we end up with the same - // allocations being utilised for the same descriptor across all map uses, - // this prevents runtime issues such as not appropriately releasing or - // deleting all mapped data. - auto find = localBoxAllocas.find(descriptor.getAsOpaquePointer()); - if (find != localBoxAllocas.end()) { - builder.create(loc, descriptor, find->second); - descriptor = find->second; - } else { - mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint(); - mlir::Block *allocaBlock = builder.getAllocaBlock(); - assert(allocaBlock && "No alloca block found for this top level op"); - builder.setInsertionPointToStart(allocaBlock); - auto alloca = builder.create(loc, descriptor.getType()); - builder.restoreInsertionPoint(insPt); - builder.create(loc, descriptor, alloca); - localBoxAllocas[descriptor.getAsOpaquePointer()] = alloca; - descriptor = alloca; - } - } + mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint(); + mlir::Block *allocaBlock = builder.getAllocaBlock(); + mlir::Location loc = boxMap->getLoc(); + assert(allocaBlock && "No alloca block found for this top level op"); + builder.setInsertionPointToStart(allocaBlock); + auto alloca = builder.create(loc, descriptor.getType()); + builder.restoreInsertionPoint(insPt); + builder.create(loc, descriptor, alloca); + return alloca; + } + /// Function that generates a FIR operation accessing the descriptor's + /// base address (BoxOffsetOp) and a MapInfoOp for it. The most + /// important thing to note is that we normally move the bounds from + /// the descriptor map onto the base address map. + mlir::omp::MapInfoOp genBaseAddrMap(mlir::Value descriptor, + mlir::OperandRange bounds, + int64_t mapType, + fir::FirOpBuilder &builder) { + mlir::Location loc = descriptor.getLoc(); mlir::Value baseAddrAddr = builder.create( loc, descriptor, fir::BoxFieldAttr::base_addr); // Member of the descriptor pointing at the allocated data - mlir::Value baseAddr = builder.create( + return builder.create( loc, baseAddrAddr.getType(), descriptor, mlir::TypeAttr::get(llvm::cast( fir::unwrapRefType(baseAddrAddr.getType())) .getElementType()), baseAddrAddr, /*members=*/mlir::SmallVector{}, - /*member_index=*/mlir::DenseIntElementsAttr{}, op.getBounds(), - builder.getIntegerAttr(builder.getIntegerType(64, false), - op.getMapType().value()), + /*membersIndex=*/mlir::ArrayAttr{}, bounds, + builder.getIntegerAttr(builder.getIntegerType(64, false), mapType), builder.getAttr( mlir::omp::VariableCaptureKind::ByRef), /*name=*/builder.getStringAttr(""), /*partial_map=*/builder.getBoolAttr(false)); + } + + /// This function adjusts the member indices vector to include a new + /// base address member. We take the position of the descriptor in + /// the member indices list, which is the index data that the base + /// addresses index will be based off of, as the base address is + /// a member of the descriptor. We must also alter other members + /// that are members of this descriptor to account for the addition + /// of the base address index. + void adjustMemberIndices( + llvm::SmallVectorImpl> &memberIndices, + size_t memberIndex) { + llvm::SmallVector baseAddrIndex = memberIndices[memberIndex]; + + // If we find another member that is "derived/a member of" the descriptor + // that is not the descriptor itself, we must insert a 0 for the new base + // address we have just added for the descriptor into the list at the + // appropriate position to maintain correctness of the positional/index data + // for that member. + for (llvm::SmallVector &member : memberIndices) + if (member.size() > baseAddrIndex.size() && + std::equal(baseAddrIndex.begin(), baseAddrIndex.end(), + member.begin())) + member.insert(std::next(member.begin(), baseAddrIndex.size()), 0); + + // Add the base address index to the main base address member data + baseAddrIndex.push_back(0); + + // Insert our newly created baseAddrIndex into the larger list of indices at + // the correct location. + memberIndices.insert(std::next(memberIndices.begin(), memberIndex + 1), + baseAddrIndex); + } + + /// Adjusts the descriptor's map type. The main alteration that is done + /// currently is transforming the map type to `OMP_MAP_TO` where possible. + /// This is because we will always need to map the descriptor to device + /// (or at the very least it seems to be the case currently with the + /// current lowered kernel IR), as without the appropriate descriptor + /// information on the device there is a risk of the kernel IR + /// requesting for various data that will not have been copied to + /// perform things like indexing. This can cause segfaults and + /// memory access errors. However, we do not need this data mapped + /// back to the host from the device, as per the OpenMP spec we cannot alter + /// the data via resizing or deletion on the device. Discarding any + /// descriptor alterations via no map back is reasonable (and required + /// for certain segments of descriptor data like the type descriptor that are + /// global constants). This alteration is only inapplicable to `target exit` + /// and `target update` currently, and that's due to `target exit` not + /// allowing `to` mappings, and `target update` not allowing both `to` and + /// `from` simultaneously. We currently try to maintain the `implicit` flag + /// where necessary, although it does not seem strictly required. + unsigned long getDescriptorMapType(unsigned long mapTypeFlag, + mlir::Operation *target) { + if (llvm::isa_and_nonnull(target)) + return mapTypeFlag; + + bool hasImplicitMap = + (llvm::omp::OpenMPOffloadMappingFlags(mapTypeFlag) & + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT) == + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT; + + return llvm::to_underlying( + hasImplicitMap + ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO | + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT + : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO); + } + + mlir::omp::MapInfoOp genDescriptorMemberMaps(mlir::omp::MapInfoOp op, + fir::FirOpBuilder &builder, + mlir::Operation *target) { + llvm::SmallVector mapMemberUsers; + getMemberUserList(op, mapMemberUsers); // TODO: map the addendum segment of the descriptor, similarly to the - // above base address/data pointer member. + // base address/data pointer member. + mlir::Value descriptor = getDescriptorFromBoxMap(op, builder); + auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(), + op.getMapType().value_or(0), builder); + mlir::ArrayAttr newMembersAttr; + mlir::SmallVector newMembers; + llvm::SmallVector> memberIndices; - auto addOperands = [&](mlir::OperandRange &operandsArr, - mlir::MutableOperandRange &mutableOpRange, - auto directiveOp) { - llvm::SmallVector newMapOps; - for (size_t i = 0; i < operandsArr.size(); ++i) { - if (operandsArr[i] == op) { - // Push new implicit maps generated for the descriptor. - newMapOps.push_back(baseAddr); - - // for TargetOp's which have IsolatedFromAbove we must align the - // new additional map operand with an appropriate BlockArgument, - // as the printing and later processing currently requires a 1:1 - // mapping of BlockArgs to MapInfoOp's at the same placement in - // each array (BlockArgs and MapOperands). - if (directiveOp) { - directiveOp.getRegion().insertArgument(i, baseAddr.getType(), loc); - } - } - newMapOps.push_back(operandsArr[i]); + if (!mapMemberUsers.empty() || !op.getMembers().empty()) + getMemberIndicesAsVectors( + !mapMemberUsers.empty() ? mapMemberUsers[0].parent : op, + memberIndices); + + // If the operation that we are expanding with a descriptor has a user + // (parent), then we have to expand the parent's member indices to reflect + // the adjusted member indices for the base address insertion. However, if + // it does not then we are expanding a MapInfoOp without any pre-existing + // member information to now have one new member for the base address, or + // we are expanding a parent that is a descriptor and we have to adjust + // all of its members to reflect the insertion of the base address. + if (!mapMemberUsers.empty()) { + // Currently, there should only be one user per map when this pass + // is executed. Either a parent map, holding the current map in its + // member list, or a target operation that holds a map clause. This + // may change in the future if we aim to refactor the MLIR for map + // clauses to allow sharing of duplicate maps across target + // operations. + assert(mapMemberUsers.size() == 1 && + "OMPMapInfoFinalization currently only supports single users of a " + "MapInfoOp"); + ParentAndPlacement mapUser = mapMemberUsers[0]; + adjustMemberIndices(memberIndices, mapUser.index); + llvm::SmallVector newMemberOps; + for (auto v : mapUser.parent.getMembers()) { + newMemberOps.push_back(v); + if (v == op) + newMemberOps.push_back(baseAddr); + } + mapUser.parent.getMembersMutable().assign(newMemberOps); + mapUser.parent.setMembersIndexAttr( + builder.create2DI64ArrayAttr(memberIndices)); + } else { + newMembers.push_back(baseAddr); + if (!op.getMembers().empty()) { + for (auto &indices : memberIndices) + indices.insert(indices.begin(), 0); + memberIndices.insert(memberIndices.begin(), {0}); + newMembersAttr = builder.create2DI64ArrayAttr(memberIndices); + newMembers.append(op.getMembers().begin(), op.getMembers().end()); + } else { + llvm::SmallVector> memberIdx = {{0}}; + newMembersAttr = builder.create2DI64ArrayAttr(memberIdx); } - mutableOpRange.assign(newMapOps); - }; - if (auto mapClauseOwner = - llvm::dyn_cast(target)) { - mlir::OperandRange mapOperandsArr = mapClauseOwner.getMapVars(); - mlir::MutableOperandRange mapMutableOpRange = - mapClauseOwner.getMapVarsMutable(); - mlir::omp::TargetOp targetOp = - llvm::dyn_cast(target); - addOperands(mapOperandsArr, mapMutableOpRange, targetOp); - } - if (auto targetDataOp = llvm::dyn_cast(target)) { - mlir::OperandRange useDevAddrArr = targetDataOp.getUseDeviceAddrVars(); - mlir::MutableOperandRange useDevAddrMutableOpRange = - targetDataOp.getUseDeviceAddrVarsMutable(); - addOperands(useDevAddrArr, useDevAddrMutableOpRange, targetDataOp); } - mlir::Value newDescParentMapOp = builder.create( - op->getLoc(), op.getResult().getType(), descriptor, - mlir::TypeAttr::get(fir::unwrapRefType(descriptor.getType())), - /*varPtrPtr=*/mlir::Value{}, - /*members=*/mlir::SmallVector{baseAddr}, - /*members_index=*/ - mlir::DenseIntElementsAttr::get( - mlir::VectorType::get( - llvm::ArrayRef({1, 1}), - mlir::IntegerType::get(builder.getContext(), 32)), - llvm::ArrayRef({0})), - /*bounds=*/mlir::SmallVector{}, - builder.getIntegerAttr(builder.getIntegerType(64, false), - op.getMapType().value()), - op.getMapCaptureTypeAttr(), op.getNameAttr(), op.getPartialMapAttr()); - op.replaceAllUsesWith(newDescParentMapOp); + mlir::omp::MapInfoOp newDescParentMapOp = + builder.create( + op->getLoc(), op.getResult().getType(), descriptor, + mlir::TypeAttr::get(fir::unwrapRefType(descriptor.getType())), + /*varPtrPtr=*/mlir::Value{}, newMembers, newMembersAttr, + /*bounds=*/mlir::SmallVector{}, + builder.getIntegerAttr( + builder.getIntegerType(64, false), + getDescriptorMapType(op.getMapType().value_or(0), target)), + op.getMapCaptureTypeAttr(), op.getNameAttr(), + /*partial_map=*/builder.getBoolAttr(false)); + op.replaceAllUsesWith(newDescParentMapOp.getResult()); op->erase(); + return newDescParentMapOp; } // We add all mapped record members not directly used in the target region @@ -225,32 +362,99 @@ class MapInfoFinalizationPass fir::FirOpBuilder &builder, mlir::Operation *target) { auto mapClauseOwner = - llvm::dyn_cast(target); + llvm::dyn_cast_if_present( + target); + // TargetDataOp is technically a MapClauseOwningOpInterface, so we + // do not need to explicitly check for the extra cases here for use_device + // addr/ptr if (!mapClauseOwner) return; - llvm::SmallVector newMapOps; - mlir::OperandRange mapVarsArr = mapClauseOwner.getMapVars(); - auto targetOp = llvm::dyn_cast(target); - - for (size_t i = 0; i < mapVarsArr.size(); ++i) { - if (mapVarsArr[i] == op) { - for (auto [j, mapMember] : llvm::enumerate(op.getMembers())) { - newMapOps.push_back(mapMember); - // for TargetOp's which have IsolatedFromAbove we must align the - // new additional map operand with an appropriate BlockArgument, - // as the printing and later processing currently requires a 1:1 - // mapping of BlockArgs to MapInfoOp's at the same placement in - // each array (BlockArgs and MapVars). - if (targetOp) { - targetOp.getRegion().insertArgument(i + j, mapMember.getType(), - targetOp->getLoc()); - } + auto addOperands = [&](mlir::MutableOperandRange &mutableOpRange, + mlir::Operation *directiveOp, + unsigned blockArgInsertIndex = 0) { + if (!llvm::is_contained(mutableOpRange.getAsOperandRange(), + op.getResult())) + return; + + // There doesn't appear to be a simple way to convert MutableOperandRange + // to a vector currently, so we instead use a for_each to populate our + // vector. + llvm::SmallVector newMapOps; + newMapOps.reserve(mutableOpRange.size()); + llvm::for_each( + mutableOpRange.getAsOperandRange(), + [&newMapOps](mlir::Value oper) { newMapOps.push_back(oper); }); + + for (auto mapMember : op.getMembers()) { + if (llvm::is_contained(mutableOpRange.getAsOperandRange(), mapMember)) + continue; + newMapOps.push_back(mapMember); + if (directiveOp) { + directiveOp->getRegion(0).insertArgument( + blockArgInsertIndex, mapMember.getType(), mapMember.getLoc()); + blockArgInsertIndex++; } } - newMapOps.push_back(mapVarsArr[i]); + + mutableOpRange.assign(newMapOps); + }; + + auto argIface = + llvm::dyn_cast(target); + + if (auto mapClauseOwner = + llvm::dyn_cast(target)) { + mlir::MutableOperandRange mapMutableOpRange = + mapClauseOwner.getMapVarsMutable(); + unsigned blockArgInsertIndex = + argIface + ? argIface.getMapBlockArgsStart() + argIface.numMapBlockArgs() + : 0; + addOperands( + mapMutableOpRange, + llvm::dyn_cast_or_null(argIface.getOperation()), + blockArgInsertIndex); + } + + if (auto targetDataOp = llvm::dyn_cast(target)) { + mlir::MutableOperandRange useDevAddrMutableOpRange = + targetDataOp.getUseDeviceAddrVarsMutable(); + addOperands(useDevAddrMutableOpRange, target, + argIface.getUseDeviceAddrBlockArgsStart() + + argIface.numUseDeviceAddrBlockArgs()); + + mlir::MutableOperandRange useDevPtrMutableOpRange = + targetDataOp.getUseDevicePtrVarsMutable(); + addOperands(useDevPtrMutableOpRange, target, + argIface.getUseDevicePtrBlockArgsStart() + + argIface.numUseDevicePtrBlockArgs()); } - mapClauseOwner.getMapVarsMutable().assign(newMapOps); + } + + // We retrieve the first user that is a Target operation, of which + // there should only be one currently. Every MapInfoOp can be tied to + // at most one Target operation and at the minimum no operations. + // This may change in the future with IR cleanups/modifications, + // in which case this pass will need updating to support cases + // where a map can have more than one user and more than one of + // those users can be a Target operation. For now, we simply + // return the first target operation encountered, which may + // be on the parent MapInfoOp in the case of a member mapping. + // In that case, we traverse the MapInfoOp chain until we + // find the first TargetOp user. + mlir::Operation *getFirstTargetUser(mlir::omp::MapInfoOp mapOp) { + for (auto *user : mapOp->getUsers()) { + if (llvm::isa(user)) + return user; + + if (auto mapUser = llvm::dyn_cast(user)) + return getFirstTargetUser(mapUser); + } + + return nullptr; } // This pass executes on omp::MapInfoOp's containing descriptor based types @@ -283,27 +487,39 @@ class MapInfoFinalizationPass localBoxAllocas.clear(); func->walk([&](mlir::omp::MapInfoOp op) { - // TODO: Currently only supports a single user for the MapInfoOp, this - // is fine for the moment as the Fortran Frontend will generate a - // new MapInfoOp per Target operation for the moment. However, when/if - // we optimise/cleanup the IR, it likely isn't too difficult to - // extend this function, it would require some modification to create a - // single new MapInfoOp per new MapInfoOp generated and share it across - // all users appropriately, making sure to only add a single member link - // per new generation for the original originating descriptor MapInfoOp. + // TODO: Currently only supports a single user for the MapInfoOp. This + // is fine for the moment, as the Fortran frontend will generate a + // new MapInfoOp with at most one user currently. In the case of + // members of other objects, like derived types, the user would be the + // parent. In cases where it's a regular non-member map, the user would + // be the target operation it is being mapped by. + // + // However, when/if we optimise/cleanup the IR we will have to extend + // this pass to support multiple users, as we may wish to have a map + // be re-used by multiple users (e.g. across multiple targets that map + // the variable and have identical map properties). assert(llvm::hasSingleElement(op->getUsers()) && "OMPMapInfoFinalization currently only supports single users " "of a MapInfoOp"); - if (!op.getMembers().empty()) { - addImplicitMembersToTarget(op, builder, *op->getUsers().begin()); - } else if (fir::isTypeWithDescriptor(op.getVarType()) || - mlir::isa_and_present( - op.getVarPtr().getDefiningOp())) { + if (fir::isTypeWithDescriptor(op.getVarType()) || + mlir::isa_and_present( + op.getVarPtr().getDefiningOp())) { builder.setInsertionPoint(op); - genDescriptorMemberMaps(op, builder, *op->getUsers().begin()); + mlir::Operation *targetUser = getFirstTargetUser(op); + assert(targetUser && "expected user of map operation was not found"); + genDescriptorMemberMaps(op, builder, targetUser); } }); + + // Wait until after we have generated all of our maps to add them onto + // the target's block arguments, simplifying the process as there would be + // no need to avoid accidental duplicate additions. + func->walk([&](mlir::omp::MapInfoOp op) { + mlir::Operation *targetUser = getFirstTargetUser(op); + assert(targetUser && "expected user of map operation was not found"); + addImplicitMembersToTarget(op, builder, targetUser); + }); }); } }; diff --git a/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp index 2fa55844aec7c743ff371ceec8f5f5a3d5ca56dc..289e648eed85467bde7017a98d2365e2b27126f5 100644 --- a/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp +++ b/flang/lib/Optimizer/OpenMP/MapsForPrivatizedSymbols.cpp @@ -92,7 +92,7 @@ class MapsForPrivatizedSymbolsPass .getElementType()), /*varPtrPtr=*/Value{}, /*members=*/SmallVector{}, - /*member_index=*/DenseIntElementsAttr{}, + /*member_index=*/mlir::ArrayAttr{}, /*bounds=*/ValueRange{}, builder.getIntegerAttr(builder.getIntegerType(64, /*isSigned=*/false), mapTypeTo), diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index a9144079915912686def49ddb68d1ab1c2e06e3e..31af3531641dda19291e3c1024a899113a2b09e9 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -212,7 +212,7 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, /// \param pm - MLIR pass manager that will hold the pipeline definition /// \param optLevel - optimization level used for creating FIR optimization /// passes pipeline -void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, +void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, bool enableOpenMP, llvm::OptimizationLevel optLevel) { if (optLevel.isOptimizingForSpeed()) { addCanonicalizerPassWithoutRegionSimplification(pm); @@ -230,6 +230,8 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, pm.addPass(hlfir::createLowerHLFIRIntrinsics()); pm.addPass(hlfir::createBufferizeHLFIR()); pm.addPass(hlfir::createConvertHLFIRtoFIR()); + if (enableOpenMP) + pm.addPass(flangomp::createLowerWorkshare()); } /// Create a pass pipeline for handling certain OpenMP transformations needed @@ -303,7 +305,7 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, void createMLIRToLLVMPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig &config, llvm::StringRef inputFilename) { - fir::createHLFIRToFIRPassPipeline(pm, config.OptLevel); + fir::createHLFIRToFIRPassPipeline(pm, config.EnableOpenMP, config.OptLevel); // Add default optimizer pass pipeline. fir::createDefaultFIROptimizerPassPipeline(pm, config); diff --git a/flang/lib/Optimizer/Transforms/CUFCommon.cpp b/flang/lib/Optimizer/Transforms/CUFCommon.cpp index 5eca86529f9e17c3c2736ea556b1d58191ae85f2..162df8f9cab9cd0924ffbc82c7602a20d6eea41e 100644 --- a/flang/lib/Optimizer/Transforms/CUFCommon.cpp +++ b/flang/lib/Optimizer/Transforms/CUFCommon.cpp @@ -22,9 +22,6 @@ mlir::gpu::GPUModuleOp cuf::getOrCreateGPUModule(mlir::ModuleOp mod, mlir::OpBuilder builder(ctx); auto gpuMod = builder.create(mod.getLoc(), cudaDeviceModuleName); - llvm::SmallVector targets; - targets.push_back(mlir::NVVM::NVVMTargetAttr::get(ctx)); - gpuMod.setTargetsAttr(builder.getArrayAttr(targets)); mlir::Block::iterator insertPt(mod.getBodyRegion().front().end()); symTab.insert(gpuMod, insertPt); return gpuMod; diff --git a/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp b/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp index a69b47ff7439112a82dc4e2484b2f1d5b88eb924..714b0b291be1e9a96751864110f2ced589d5041e 100644 --- a/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp +++ b/flang/lib/Optimizer/Transforms/CUFDeviceGlobal.cpp @@ -26,25 +26,37 @@ namespace fir { namespace { +static void processAddrOfOp(fir::AddrOfOp addrOfOp, + mlir::SymbolTable &symbolTable, bool onlyConstant) { + if (auto globalOp = symbolTable.lookup( + addrOfOp.getSymbol().getRootReference().getValue())) { + bool isCandidate{(onlyConstant ? globalOp.getConstant() : true) && + !globalOp.getDataAttr()}; + if (isCandidate) + globalOp.setDataAttrAttr(cuf::DataAttributeAttr::get( + addrOfOp.getContext(), globalOp.getConstant() + ? cuf::DataAttribute::Constant + : cuf::DataAttribute::Device)); + } +} + static void prepareImplicitDeviceGlobals(mlir::func::FuncOp funcOp, mlir::SymbolTable &symbolTable, bool onlyConstant = true) { auto cudaProcAttr{ funcOp->getAttrOfType(cuf::getProcAttrName())}; - if (!cudaProcAttr || cudaProcAttr.getValue() == cuf::ProcAttribute::Host) - return; - for (auto addrOfOp : funcOp.getBody().getOps()) { - if (auto globalOp = symbolTable.lookup( - addrOfOp.getSymbol().getRootReference().getValue())) { - bool isCandidate{(onlyConstant ? globalOp.getConstant() : true) && - !globalOp.getDataAttr()}; - if (isCandidate) - globalOp.setDataAttrAttr(cuf::DataAttributeAttr::get( - funcOp.getContext(), globalOp.getConstant() - ? cuf::DataAttribute::Constant - : cuf::DataAttribute::Device)); + if (!cudaProcAttr || cudaProcAttr.getValue() == cuf::ProcAttribute::Host) { + // Look for globlas in CUF KERNEL DO operations. + for (auto cufKernelOp : funcOp.getBody().getOps()) { + cufKernelOp.walk([&](fir::AddrOfOp addrOfOp) { + processAddrOfOp(addrOfOp, symbolTable, onlyConstant); + }); } + return; } + funcOp.walk([&](fir::AddrOfOp addrOfOp) { + processAddrOfOp(addrOfOp, symbolTable, onlyConstant); + }); } class CUFDeviceGlobal : public fir::impl::CUFDeviceGlobalBase { diff --git a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp index 8e9de3d32815257b2c5384196c8e0b2ad0802729..f1ebd08967b9a18adbc7e4d518a0902c327267f7 100644 --- a/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp +++ b/flang/lib/Optimizer/Transforms/CUFOpConversion.cpp @@ -140,8 +140,9 @@ mlir::Value getDeviceAddress(mlir::PatternRewriter &rewriter, llvm::SmallVector args{fir::runtime::createArguments( builder, loc, fTy, inputArg, sourceFile, sourceLine)}; auto call = rewriter.create(loc, callee, args); - - return call->getResult(0); + mlir::Value cast = createConvertOp( + rewriter, loc, declareOp.getMemref().getType(), call->getResult(0)); + return cast; } template @@ -251,6 +252,8 @@ struct CUFDeallocateOpConversion static bool inDeviceContext(mlir::Operation *op) { if (op->getParentOfType()) return true; + if (auto funcOp = op->getParentOfType()) + return true; if (auto funcOp = op->getParentOfType()) { if (auto cudaProcAttr = funcOp.getOperation()->getAttrOfType( @@ -265,24 +268,23 @@ static bool inDeviceContext(mlir::Operation *op) { static int computeWidth(mlir::Location loc, mlir::Type type, fir::KindMapping &kindMap) { auto eleTy = fir::unwrapSequenceType(type); - int width = 0; - if (auto t{mlir::dyn_cast(eleTy)}) { - width = t.getWidth() / 8; - } else if (auto t{mlir::dyn_cast(eleTy)}) { - width = t.getWidth() / 8; - } else if (eleTy.isInteger(1)) { - width = 1; - } else if (auto t{mlir::dyn_cast(eleTy)}) { - int kind = t.getFKind(); - width = kindMap.getLogicalBitsize(kind) / 8; - } else if (auto t{mlir::dyn_cast(eleTy)}) { + if (auto t{mlir::dyn_cast(eleTy)}) + return t.getWidth() / 8; + if (auto t{mlir::dyn_cast(eleTy)}) + return t.getWidth() / 8; + if (eleTy.isInteger(1)) + return 1; + if (auto t{mlir::dyn_cast(eleTy)}) + return kindMap.getLogicalBitsize(t.getFKind()) / 8; + if (auto t{mlir::dyn_cast(eleTy)}) { int elemSize = mlir::cast(t.getElementType()).getWidth() / 8; - width = 2 * elemSize; - } else { - llvm::report_fatal_error("unsupported type"); + return 2 * elemSize; } - return width; + if (auto t{mlir::dyn_cast_or_null(eleTy)}) + return kindMap.getCharacterBitsize(t.getFKind()) / 8; + mlir::emitError(loc, "unsupported type"); + return 0; } struct CUFAllocOpConversion : public mlir::OpRewritePattern { @@ -321,9 +323,15 @@ struct CUFAllocOpConversion : public mlir::OpRewritePattern { builder.createIntegerConstant(loc, builder.getIndexType(), width); } else if (auto seqTy = mlir::dyn_cast_or_null( op.getInType())) { - mlir::Value width = builder.createIntegerConstant( - loc, builder.getIndexType(), - computeWidth(loc, seqTy.getEleTy(), kindMap)); + std::size_t size = 0; + if (fir::isa_derived(seqTy.getEleTy())) { + mlir::Type structTy = typeConverter->convertType(seqTy.getEleTy()); + size = dl->getTypeSizeInBits(structTy) / 8; + } else { + size = computeWidth(loc, seqTy.getEleTy(), kindMap); + } + mlir::Value width = + builder.createIntegerConstant(loc, builder.getIndexType(), size); mlir::Value nbElem; if (fir::sequenceWithNonConstantShape(seqTy)) { assert(!op.getShape().empty() && "expect shape with dynamic arrays"); @@ -465,9 +473,16 @@ static mlir::Value emboxSrc(mlir::PatternRewriter &rewriter, mlir::Type srcTy = fir::unwrapRefType(op.getSrc().getType()); if (fir::isa_trivial(srcTy) && mlir::matchPattern(op.getSrc().getDefiningOp(), mlir::m_Constant())) { + mlir::Value src = op.getSrc(); + if (srcTy.isInteger(1)) { + // i1 is not a supported type in the descriptor and it is actually coming + // from a LOGICAL constant. Store it as a fir.logical. + srcTy = fir::LogicalType::get(rewriter.getContext(), 4); + src = createConvertOp(rewriter, loc, srcTy, src); + } // Put constant in memory if it is not. mlir::Value alloc = builder.createTemporary(loc, srcTy); - builder.create(loc, op.getSrc(), alloc); + builder.create(loc, src, alloc); addr = alloc; } else { addr = getDeviceAddress(rewriter, op.getSrcMutable(), symtab); @@ -507,8 +522,11 @@ struct CUFDataTransferOpConversion using OpRewritePattern::OpRewritePattern; CUFDataTransferOpConversion(mlir::MLIRContext *context, - const mlir::SymbolTable &symtab) - : OpRewritePattern(context), symtab{symtab} {} + const mlir::SymbolTable &symtab, + mlir::DataLayout *dl, + const fir::LLVMTypeConverter *typeConverter) + : OpRewritePattern(context), symtab{symtab}, dl{dl}, + typeConverter{typeConverter} {} mlir::LogicalResult matchAndRewrite(cuf::DataTransferOp op, @@ -545,8 +563,9 @@ struct CUFDataTransferOpConversion // until we have more infrastructure. mlir::Value src = emboxSrc(rewriter, op, symtab); mlir::Value dst = emboxDst(rewriter, op, symtab); - mlir::func::FuncOp func = fir::runtime::getRuntimeFunc(loc, builder); + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc( + loc, builder); auto fTy = func.getFunctionType(); mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); mlir::Value sourceLine = @@ -561,13 +580,21 @@ struct CUFDataTransferOpConversion mlir::Type i64Ty = builder.getI64Type(); mlir::Value nbElement; if (op.getShape()) { - auto shapeOp = - mlir::dyn_cast(op.getShape().getDefiningOp()); - nbElement = rewriter.create(loc, i64Ty, - shapeOp.getExtents()[0]); - for (unsigned i = 1; i < shapeOp.getExtents().size(); ++i) { - auto operand = rewriter.create( - loc, i64Ty, shapeOp.getExtents()[i]); + llvm::SmallVector extents; + if (auto shapeOp = + mlir::dyn_cast(op.getShape().getDefiningOp())) { + extents = shapeOp.getExtents(); + } else if (auto shapeShiftOp = mlir::dyn_cast( + op.getShape().getDefiningOp())) { + for (auto i : llvm::enumerate(shapeShiftOp.getPairs())) + if (i.index() & 1) + extents.push_back(i.value()); + } + + nbElement = rewriter.create(loc, i64Ty, extents[0]); + for (unsigned i = 1; i < extents.size(); ++i) { + auto operand = + rewriter.create(loc, i64Ty, extents[i]); nbElement = rewriter.create(loc, nbElement, operand); } @@ -576,7 +603,14 @@ struct CUFDataTransferOpConversion nbElement = builder.createIntegerConstant( loc, i64Ty, seqTy.getConstantArraySize()); } - int width = computeWidth(loc, dstTy, kindMap); + unsigned width = 0; + if (fir::isa_derived(fir::unwrapSequenceType(dstTy))) { + mlir::Type structTy = + typeConverter->convertType(fir::unwrapSequenceType(dstTy)); + width = dl->getTypeSizeInBits(structTy) / 8; + } else { + width = computeWidth(loc, dstTy, kindMap); + } mlir::Value widthValue = rewriter.create( loc, i64Ty, rewriter.getIntegerAttr(i64Ty, width)); mlir::Value bytes = @@ -594,6 +628,12 @@ struct CUFDataTransferOpConversion mlir::Value dst = getDeviceAddress(rewriter, op.getDstMutable(), symtab); mlir::Value src = getDeviceAddress(rewriter, op.getSrcMutable(), symtab); + // Materialize the src if constant. + if (matchPattern(src.getDefiningOp(), mlir::m_Constant())) { + mlir::Value temp = builder.createTemporary(loc, srcTy); + builder.create(loc, src, temp); + src = temp; + } llvm::SmallVector args{ fir::runtime::createArguments(builder, loc, fTy, dst, src, bytes, modeValue, sourceFile, sourceLine)}; @@ -613,9 +653,23 @@ struct CUFDataTransferOpConversion loc, builder); mlir::Value dst = op.getDst(); mlir::Value src = op.getSrc(); - - if (!mlir::isa(srcTy)) + if (!mlir::isa(srcTy)) { src = emboxSrc(rewriter, op, symtab); + if (fir::isa_trivial(srcTy)) + func = fir::runtime::getRuntimeFunc( + loc, builder); + } + auto materializeBoxIfNeeded = [&](mlir::Value val) -> mlir::Value { + if (mlir::isa(val.getDefiningOp())) { + // Materialize the box to memory to be able to call the runtime. + mlir::Value box = builder.createTemporary(loc, val.getType()); + builder.create(loc, val, box); + return box; + } + return val; + }; + src = materializeBoxIfNeeded(src); + dst = materializeBoxIfNeeded(dst); auto fTy = func.getFunctionType(); mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); @@ -647,6 +701,8 @@ struct CUFDataTransferOpConversion private: const mlir::SymbolTable &symtab; + mlir::DataLayout *dl; + const fir::LLVMTypeConverter *typeConverter; }; struct CUFLaunchOpConversion @@ -749,6 +805,7 @@ void cuf::populateCUFToFIRConversionPatterns( patterns.insert(patterns.getContext(), &dl, &converter); patterns.insert(patterns.getContext()); - patterns.insert( - patterns.getContext(), symtab); + patterns.insert(patterns.getContext(), symtab, + &dl, &converter); + patterns.insert(patterns.getContext(), symtab); } diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp index 0187524d76cdd5c3321aa24acc6fb6577ae91a7b..cc99698ead33f7d99a4e97b3b2382c0817b12015 100644 --- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -629,7 +629,12 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType( return convertCharacterType(charTy, fileAttr, scope, declOp, /*hasDescriptor=*/true); - mlir::LLVM::DITypeAttr elTyAttr = convertType(elTy, fileAttr, scope, declOp); + // If elTy is null or none then generate a void* + mlir::LLVM::DITypeAttr elTyAttr; + if (!elTy || mlir::isa(elTy)) + elTyAttr = mlir::LLVM::DINullTypeAttr::get(context); + else + elTyAttr = convertType(elTy, fileAttr, scope, declOp); return mlir::LLVM::DIDerivedTypeAttr::get( context, llvm::dwarf::DW_TAG_pointer_type, @@ -679,8 +684,8 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, return genBasicType(context, mlir::StringAttr::get(context, "integer"), llvmTypeConverter.getIndexTypeBitwidth(), llvm::dwarf::DW_ATE_signed); - } else if (auto boxTy = mlir::dyn_cast_or_null(Ty)) { - auto elTy = boxTy.getElementType(); + } else if (auto boxTy = mlir::dyn_cast_or_null(Ty)) { + auto elTy = boxTy.getEleTy(); if (auto seqTy = mlir::dyn_cast_or_null(elTy)) return convertBoxedSequenceType(seqTy, fileAttr, scope, declOp, false, false); @@ -692,7 +697,9 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, return convertPointerLikeType(ptrTy.getElementType(), fileAttr, scope, declOp, /*genAllocated=*/false, /*genAssociated=*/true); - return genPlaceholderType(context); + return convertPointerLikeType(elTy, fileAttr, scope, declOp, + /*genAllocated=*/false, + /*genAssociated=*/false); } else { // FIXME: These types are currently unhandled. We are generating a // placeholder type to allow us to test supported bits. diff --git a/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp b/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp index 648628fd1c9af05a32ef320839f7619a2384c740..cfd90ff723793be64758a57d648eb23abec027c2 100644 --- a/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp +++ b/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp @@ -12,6 +12,7 @@ #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/InternalNames.h" #include "flang/Optimizer/Transforms/Passes.h" +#include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/SymbolTable.h" #include "mlir/Pass/Pass.h" @@ -58,26 +59,36 @@ void ExternalNameConversionPass::runOnOperation() { auto *context = &getContext(); llvm::DenseMap remappings; - // Update names of external Fortran functions and names of Common Block - // globals. - for (auto &funcOrGlobal : op->getRegion(0).front()) { - if (llvm::isa(funcOrGlobal) || - llvm::isa(funcOrGlobal)) { - auto symName = funcOrGlobal.getAttrOfType( - mlir::SymbolTable::getSymbolAttrName()); - auto deconstructedName = fir::NameUniquer::deconstruct(symName); - if (fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) { - auto newName = - mangleExternalName(deconstructedName, appendUnderscoreOpt); - auto newAttr = mlir::StringAttr::get(context, newName); - mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr); - auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr); - remappings.try_emplace(symName, newSymRef); - if (llvm::isa(funcOrGlobal)) - funcOrGlobal.setAttr(fir::getInternalFuncNameAttrName(), symName); + + auto renameFuncOrGlobalInModule = [&](mlir::Operation *module) { + for (auto &funcOrGlobal : module->getRegion(0).front()) { + if (llvm::isa(funcOrGlobal) || + llvm::isa(funcOrGlobal)) { + auto symName = funcOrGlobal.getAttrOfType( + mlir::SymbolTable::getSymbolAttrName()); + auto deconstructedName = fir::NameUniquer::deconstruct(symName); + if (fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) { + auto newName = + mangleExternalName(deconstructedName, appendUnderscoreOpt); + auto newAttr = mlir::StringAttr::get(context, newName); + mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr); + auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr); + remappings.try_emplace(symName, newSymRef); + if (llvm::isa(funcOrGlobal)) + funcOrGlobal.setAttr(fir::getInternalFuncNameAttrName(), symName); + } } } - } + }; + + // Update names of external Fortran functions and names of Common Block + // globals. + renameFuncOrGlobalInModule(op); + + // Do the same in GPU modules. + if (auto mod = mlir::dyn_cast_or_null(*op)) + for (auto gpuMod : mod.getOps()) + renameFuncOrGlobalInModule(gpuMod); if (remappings.empty()) return; diff --git a/flang/lib/Parser/executable-parsers.cpp b/flang/lib/Parser/executable-parsers.cpp index 5057e89164c9f289a9c233cb6ab5ffb45e4cc7b2..730165613d91db51d7ad8734cb75892651105cc2 100644 --- a/flang/lib/Parser/executable-parsers.cpp +++ b/flang/lib/Parser/executable-parsers.cpp @@ -563,11 +563,15 @@ TYPE_PARSER(("REDUCTION"_tok || "REDUCE"_tok) >> parenthesized(construct(Parser{}, ":" >> nonemptyList(scalar(variable))))) +TYPE_PARSER("<<<" >> + construct(gridOrBlock, + "," >> gridOrBlock, + maybe((", 0 ,"_tok || ", STREAM ="_tok) >> scalarIntExpr) / ">>>")) + TYPE_PARSER(sourced(beginDirective >> "$CUF KERNEL DO"_tok >> construct( - maybe(parenthesized(scalarIntConstantExpr)), "<<<" >> gridOrBlock, - "," >> gridOrBlock, - maybe((", 0 ,"_tok || ", STREAM ="_tok) >> scalarIntExpr) / ">>>", + maybe(parenthesized(scalarIntConstantExpr)), + maybe(Parser{}), many(Parser{}) / endDirective))) TYPE_CONTEXT_PARSER("!$CUF KERNEL DO construct"_en_US, extension(construct( diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index a46b06dce001f9ae9e3ed9973fb88ba62b0f2ba7..630acf9a6b256cbb01423da1dfabb26ad72dba58 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -97,7 +97,7 @@ template struct MapModifiers { // Parsing of mappers is not supported yet. using TypeModParser = Parser; - using IterParser = Parser; + using IterParser = Parser; using TypeParser = Parser; using ModParser = ConcatSeparated; @@ -131,9 +131,8 @@ template struct MotionModifiers { constexpr MotionModifiers(const MotionModifiers &) = default; constexpr MotionModifiers(MotionModifiers &&) = default; - // Parsing of mappers if not implemented yet. using ExpParser = Parser; - using IterParser = Parser; + using IterParser = Parser; using ModParser = ConcatSeparated; using resultType = typename ModParser::resultType; @@ -191,6 +190,8 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list &&names) { makeEntityList(std::move(names))); } +// --- Parsers for clause modifiers ----------------------------------- + TYPE_PARSER(construct( // Using Parser or Parser has the problem // that they will attempt to treat what follows the '=' as initialization. @@ -207,14 +208,40 @@ TYPE_PARSER(construct( makeIterSpecDecl, nonemptyList(Parser{}) / "="_tok)), subscriptTriplet)) +TYPE_PARSER(construct( + "SINK" >> pure(OmpDependenceType::Value::Sink) || + "SOURCE" >> pure(OmpDependenceType::Value::Source))) + // [5.0] 2.1.6 iterator -> iterator-specifier-list -TYPE_PARSER(construct("ITERATOR" >> +TYPE_PARSER(construct("ITERATOR" >> parenthesized(nonemptyList(sourced(Parser{}))))) +// 2.15.3.7 LINEAR (linear-list: linear-step) +// linear-list -> list | modifier(list) +// linear-modifier -> REF | VAL | UVAL +TYPE_PARSER(construct( // + "REF" >> pure(OmpLinearModifier::Value::Ref) || + "VAL" >> pure(OmpLinearModifier::Value::Val) || + "UVAL" >> pure(OmpLinearModifier::Value::Uval))) + +// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) +TYPE_PARSER(construct(Parser{}) || + construct(Parser{})) + +TYPE_PARSER(construct( + "DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) || + "IN"_id >> pure(OmpTaskDependenceType::Value::In) || + "INOUT"_id >> pure(OmpTaskDependenceType::Value::Inout) || + "INOUTSET"_id >> pure(OmpTaskDependenceType::Value::Inoutset) || + "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) || + "OUT" >> pure(OmpTaskDependenceType::Value::Out))) + +// --- Parsers for clauses -------------------------------------------- + // [5.0] 2.10.1 affinity([aff-modifier:] locator-list) // aff-modifier: interator-modifier TYPE_PARSER(construct( - maybe(Parser{} / ":"), Parser{})) + maybe(Parser{} / ":"), Parser{})) // 2.15.3.1 DEFAULT (PRIVATE | FIRSTPRIVATE | SHARED | NONE) TYPE_PARSER(construct( @@ -250,27 +277,32 @@ TYPE_PARSER( "TOFROM" >> pure(OmpMapClause::Type::Tofrom))) template -static inline OmpMapClause makeMapClause( +static inline OmpMapClause makeMapClause(OmpMapperIdentifier &&mm, std::tuple>, - std::optional>, + std::optional>, std::optional>> &&mods, OmpObjectList &&objs) { auto &&[tm, it, ty] = std::move(mods); - return OmpMapClause{std::move(tm), std::move(it), std::move(ty), - std::move(objs), CommasEverywhere}; + return OmpMapClause{std::move(mm), std::move(tm), std::move(it), + std::move(ty), std::move(objs), CommasEverywhere}; } +TYPE_PARSER(construct( + maybe("MAPPER"_tok >> parenthesized(name) / ","_tok))) + TYPE_PARSER(construct( - applyFunction( - makeMapClause, MapModifiers(","_tok), Parser{}) || + applyFunction(makeMapClause, + Parser{}, MapModifiers(","_tok), + Parser{}) || applyFunction(makeMapClause, - MapModifiers(maybe(","_tok)), Parser{}))) + Parser{}, MapModifiers(maybe(","_tok)), + Parser{}))) // [OpenMP 5.0] // 2.19.7.2 defaultmap(implicit-behavior[:variable-category]) // implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE | // DEFAULT -// variable-category -> SCALAR | AGGREGATE | ALLOCATABLE | POINTER +// variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER TYPE_PARSER(construct( construct( "ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) || @@ -283,6 +315,7 @@ TYPE_PARSER(construct( "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)), maybe(":" >> construct( + "ALL"_id >> pure(OmpDefaultmapClause::VariableCategory::All) || "SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar) || "AGGREGATE" >> pure(OmpDefaultmapClause::VariableCategory::Aggregate) || @@ -345,21 +378,17 @@ TYPE_PARSER(construct( ":"), scalarLogicalExpr)) -// 2.15.3.6 REDUCTION (reduction-identifier: variable-name-list) -TYPE_PARSER(construct(Parser{}) || - construct(Parser{})) - TYPE_PARSER(construct( maybe( ("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) || "TASK" >> pure(OmpReductionClause::ReductionModifier::Task) || "DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) / ","), - Parser{} / ":", Parser{})) + Parser{} / ":", Parser{})) // OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list) TYPE_PARSER(construct( - Parser{} / ":", Parser{})) + Parser{} / ":", Parser{})) // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier @@ -392,18 +421,6 @@ TYPE_PARSER(construct( ":"), Parser{})) -TYPE_PARSER(construct( - "SINK" >> pure(OmpDependenceType::Type::Sink) || - "SOURCE" >> pure(OmpDependenceType::Type::Source))) - -TYPE_PARSER(construct( - "DEPOBJ" >> pure(OmpTaskDependenceType::Type::Depobj) || - "IN"_id >> pure(OmpTaskDependenceType::Type::In) || - "INOUT"_id >> pure(OmpTaskDependenceType::Type::Inout) || - "INOUTSET"_id >> pure(OmpTaskDependenceType::Type::Inoutset) || - "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Type::Mutexinoutset) || - "OUT" >> pure(OmpTaskDependenceType::Type::Out))) - // iteration-offset -> +/- non-negative-constant-expr TYPE_PARSER(construct( Parser{}, scalarIntConstantExpr)) @@ -421,7 +438,7 @@ TYPE_PARSER(construct( TYPE_CONTEXT_PARSER("Omp Depend clause"_en_US, construct( construct(construct( - maybe(Parser{} / ","_tok), + maybe(Parser{} / ","_tok), Parser{} / ":", Parser{})) || construct(Parser{}))) @@ -434,7 +451,7 @@ TYPE_PARSER(construct( template static inline MotionClause makeMotionClause( std::tuple>, - std::optional>> &&mods, + std::optional>> &&mods, OmpObjectList &&objs) { auto &&[exp, iter] = std::move(mods); return MotionClause( @@ -453,14 +470,6 @@ TYPE_PARSER(construct( applyFunction(makeMotionClause, MotionModifiers(maybe(","_tok)), Parser{}))) -// 2.15.3.7 LINEAR (linear-list: linear-step) -// linear-list -> list | modifier(list) -// linear-modifier -> REF | VAL | UVAL -TYPE_PARSER( - construct("REF" >> pure(OmpLinearModifier::Type::Ref) || - "VAL" >> pure(OmpLinearModifier::Type::Val) || - "UVAL" >> pure(OmpLinearModifier::Type::Uval))) - TYPE_CONTEXT_PARSER("Omp LINEAR clause"_en_US, construct( construct(construct( @@ -482,12 +491,11 @@ TYPE_PARSER(construct( // 2.9.5 ORDER ([order-modifier :]concurrent) TYPE_PARSER(construct( - "REPRODUCIBLE" >> pure(OmpOrderModifier::Kind::Reproducible)) || + "REPRODUCIBLE" >> pure(OmpOrderModifier::Kind::Reproducible)) || construct( - "UNCONSTRAINED" >> pure(OmpOrderModifier::Kind::Unconstrained))) + "UNCONSTRAINED" >> pure(OmpOrderModifier::Kind::Unconstrained))) -TYPE_PARSER(construct( - maybe(Parser{} / ":"), +TYPE_PARSER(construct(maybe(Parser{} / ":"), "CONCURRENT" >> pure(OmpOrderClause::Type::Concurrent))) // OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression) @@ -559,6 +567,8 @@ TYPE_PARSER( construct(construct()) || "ENTER" >> construct(construct( parenthesized(Parser{}))) || + "EXCLUSIVE" >> construct(construct( + parenthesized(Parser{}))) || "FILTER" >> construct(construct( parenthesized(scalarIntExpr))) || "FINAL" >> construct(construct( @@ -578,6 +588,8 @@ TYPE_PARSER( "IF" >> construct(construct( parenthesized(Parser{}))) || "INBRANCH" >> construct(construct()) || + "INCLUSIVE" >> construct(construct( + parenthesized(Parser{}))) || "IS_DEVICE_PTR" >> construct(construct( parenthesized(Parser{}))) || "LASTPRIVATE" >> construct(construct( @@ -790,6 +802,7 @@ TYPE_PARSER(sourced(construct(verbatim("FLUSH"_tok), TYPE_PARSER(sourced(construct(first( "BARRIER" >> pure(llvm::omp::Directive::OMPD_barrier), "ORDERED" >> pure(llvm::omp::Directive::OMPD_ordered), + "SCAN" >> pure(llvm::omp::Directive::OMPD_scan), "TARGET ENTER DATA" >> pure(llvm::omp::Directive::OMPD_target_enter_data), "TARGET EXIT DATA" >> pure(llvm::omp::Directive::OMPD_target_exit_data), "TARGET UPDATE" >> pure(llvm::omp::Directive::OMPD_target_update), @@ -839,7 +852,7 @@ TYPE_PARSER(construct( // 2.16 Declare Reduction Construct TYPE_PARSER(sourced(construct( verbatim("DECLARE REDUCTION"_tok), - "(" >> Parser{} / ":", + "(" >> Parser{} / ":", nonemptyList(Parser{}) / ":", Parser{} / ")", maybe(Parser{})))) @@ -861,6 +874,15 @@ TYPE_PARSER( TYPE_PARSER(sourced(construct( verbatim("DECLARE TARGET"_tok), Parser{}))) +// declare-mapper-specifier +TYPE_PARSER(construct( + maybe(name / ":" / !":"_tok), typeSpec / "::", name)) + +// OpenMP 5.2: 5.8.8 Declare Mapper Construct +TYPE_PARSER(sourced(construct( + verbatim("DECLARE MAPPER"_tok), + "(" >> Parser{} / ")", Parser{}))) + TYPE_PARSER(construct(Parser{}) || construct( construct( @@ -969,6 +991,8 @@ TYPE_PARSER(startOmpLine >> withMessage("expected OpenMP construct"_err_en_US, sourced(construct( Parser{}) || + construct( + Parser{}) || construct( Parser{}) || construct( diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp index 574e5fd84862e724b76dc0f93c90e32db92b6d17..24b2902f286f4b1b85eaabbdc7714e614ac3a6f5 100644 --- a/flang/lib/Parser/parse-tree.cpp +++ b/flang/lib/Parser/parse-tree.cpp @@ -253,20 +253,20 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) { return os << x.ToString(); } -OmpDependenceType::Type OmpDoacross::GetDepType() const { +OmpDependenceType::Value OmpDoacross::GetDepType() const { return common::visit( // common::visitors{ [](const OmpDoacross::Sink &) { - return OmpDependenceType::Type::Sink; + return OmpDependenceType::Value::Sink; }, [](const OmpDoacross::Source &) { - return OmpDependenceType::Type::Source; + return OmpDependenceType::Value::Source; }, }, u); } -OmpTaskDependenceType::Type OmpDependClause::TaskDep::GetTaskDepType() const { +OmpTaskDependenceType::Value OmpDependClause::TaskDep::GetTaskDepType() const { return std::get(t).v; } diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 20022f8fa984ce3cc2c17c77e3267bcdae81b7c5..4d6aaceb69c1856882a1b1f01e5193c06b168e84 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2079,7 +2079,7 @@ public: Put(" = "); Walk(std::get(x.t)); } - void Unparse(const OmpIteratorModifier &x) { + void Unparse(const OmpIterator &x) { Word("ITERATOR("); Walk(x.v); Put(")"); @@ -2093,14 +2093,24 @@ public: void Unparse(const OmpMapClause &x) { auto &typeMod = std::get>>(x.t); - auto &iter = std::get>>(x.t); + auto &iter = std::get>>(x.t); auto &type = std::get>>(x.t); + auto &mapper = std::get(x.t); // For a given list of items, if the item has a value, then walk it. // Print commas between items that have values. // Return 'true' if something did get printed, otherwise 'false'. bool needComma{false}; + if (mapper.v) { + Word("MAPPER("); + Walk(*mapper.v); + Put(")"); + needComma = true; + } if (typeMod) { + if (needComma) { + Put(", "); + } Walk(*typeMod); needComma = true; } @@ -2137,7 +2147,7 @@ public: Walk(std::get(x.t)); } void Unparse(const OmpAffinityClause &x) { - Walk(std::get>(x.t), ":"); + Walk(std::get>(x.t), ":"); Walk(std::get(x.t)); } void Unparse(const OmpAlignedClause &x) { @@ -2148,7 +2158,7 @@ public: void Unparse(const OmpFromClause &x) { auto &expect{ std::get>>(x.t)}; - auto &iter{std::get>>(x.t)}; + auto &iter{std::get>>(x.t)}; bool needComma{false}; if (expect) { Walk(*expect); @@ -2181,13 +2191,13 @@ public: void Unparse(const OmpReductionClause &x) { Walk(std::get>(x.t), ","); - Walk(std::get(x.t)); + Walk(std::get(x.t)); Put(":"); Walk(std::get(x.t)); } void Unparse(const OmpDetachClause &x) { Walk(x.v); } void Unparse(const OmpInReductionClause &x) { - Walk(std::get(x.t)); + Walk(std::get(x.t)); Put(":"); Walk(std::get(x.t)); } @@ -2253,7 +2263,7 @@ public: void Unparse(const OmpToClause &x) { auto &expect{ std::get>>(x.t)}; - auto &iter{std::get>>(x.t)}; + auto &iter{std::get>>(x.t)}; bool needComma{false}; if (expect) { Walk(*expect); @@ -2393,6 +2403,9 @@ public: case llvm::omp::Directive::OMPD_barrier: Word("BARRIER "); break; + case llvm::omp::Directive::OMPD_scan: + Word("SCAN "); + break; case llvm::omp::Directive::OMPD_taskwait: Word("TASKWAIT "); break; @@ -2632,7 +2645,7 @@ public: } void Unparse(const OpenMPDeclareReductionConstruct &x) { Put("("); - Walk(std::get(x.t)), Put(" : "); + Walk(std::get(x.t)), Put(" : "); Walk(std::get>(x.t), ","), Put(" : "); Walk(std::get(x.t)); Put(")"); @@ -2652,6 +2665,22 @@ public: EndOpenMP(); return false; }, + [&](const OpenMPDeclareMapperConstruct &z) { + Word("DECLARE MAPPER ("); + const auto &spec{std::get(z.t)}; + if (auto mapname{std::get>(spec.t)}) { + Walk(mapname); + Put(":"); + } + Walk(std::get(spec.t)); + Put("::"); + Walk(std::get(spec.t)); + Put(")"); + + Walk(std::get(z.t)); + Put("\n"); + return false; + }, [&](const OpenMPDeclareReductionConstruct &) { Word("DECLARE REDUCTION "); return true; @@ -2881,8 +2910,8 @@ public: WALK_NESTED_ENUM( OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier - WALK_NESTED_ENUM(OmpLinearModifier, Type) // OMP linear-modifier - WALK_NESTED_ENUM(OmpTaskDependenceType, Type) // OMP task-dependence-type + WALK_NESTED_ENUM(OmpLinearModifier, Value) // OMP linear-modifier + WALK_NESTED_ENUM(OmpTaskDependenceType, Value) // OMP task-dependence-type WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE @@ -2932,11 +2961,9 @@ public: Word("*"); } } - void Unparse(const CUFKernelDoConstruct::Directive &x) { - Word("!$CUF KERNEL DO"); - Walk(" (", std::get>(x.t), ")"); + void Unparse(const CUFKernelDoConstruct::LaunchConfiguration &x) { Word(" <<<"); - const auto &grid{std::get<1>(x.t)}; + const auto &grid{std::get<0>(x.t)}; if (grid.empty()) { Word("*"); } else if (grid.size() == 1) { @@ -2945,7 +2972,7 @@ public: Walk("(", grid, ",", ")"); } Word(","); - const auto &block{std::get<2>(x.t)}; + const auto &block{std::get<1>(x.t)}; if (block.empty()) { Word("*"); } else if (block.size() == 1) { @@ -2953,10 +2980,16 @@ public: } else { Walk("(", block, ",", ")"); } - if (const auto &stream{std::get<3>(x.t)}) { + if (const auto &stream{std::get<2>(x.t)}) { Word(",STREAM="), Walk(*stream); } Word(">>>"); + } + void Unparse(const CUFKernelDoConstruct::Directive &x) { + Word("!$CUF KERNEL DO"); + Walk(" (", std::get>(x.t), ")"); + Walk(std::get>( + x.t)); Walk(" ", std::get>(x.t), " "); Word("\n"); } diff --git a/flang/lib/Semantics/CMakeLists.txt b/flang/lib/Semantics/CMakeLists.txt index 41406ecf50e0041543ad212f212891d777288b9d..7855ae7eed1387022e150f4d995aa3fc0252b1ce 100644 --- a/flang/lib/Semantics/CMakeLists.txt +++ b/flang/lib/Semantics/CMakeLists.txt @@ -31,6 +31,7 @@ add_flang_library(FortranSemantics definable.cpp expression.cpp mod-file.cpp + openmp-modifiers.cpp pointer-assignment.cpp program-tree.cpp resolve-labels.cpp diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index a161d2bdf9dbb87a3c9181e7314ee1cee09bbc5b..597c280a6df8bc2c130ab48d62d2ac2e079cb064 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -135,6 +135,20 @@ static void CheckCharacterActual(evaluate::Expr &actual, dummy.type.type().kind() == actualType.type().kind() && !dummy.attrs.test( characteristics::DummyDataObject::Attr::DeducedFromActual)) { + bool actualIsAssumedRank{evaluate::IsAssumedRank(actual)}; + if (actualIsAssumedRank && + !dummy.type.attrs().test( + characteristics::TypeAndShape::Attr::AssumedRank)) { + if (!context.languageFeatures().IsEnabled( + common::LanguageFeature::AssumedRankPassedToNonAssumedRank)) { + messages.Say( + "Assumed-rank character array may not be associated with a dummy argument that is not assumed-rank"_err_en_US); + } else { + context.Warn(common::LanguageFeature::AssumedRankPassedToNonAssumedRank, + messages.at(), + "Assumed-rank character array should not be associated with a dummy argument that is not assumed-rank"_port_en_US); + } + } if (dummy.type.LEN() && actualType.LEN()) { evaluate::FoldingContext &foldingContext{context.foldingContext()}; auto dummyLength{ @@ -148,7 +162,7 @@ static void CheckCharacterActual(evaluate::Expr &actual, if (auto dummySize{evaluate::ToInt64(evaluate::Fold( foldingContext, evaluate::GetSize(dummy.type.shape())))}) { auto dummyChars{*dummySize * *dummyLength}; - if (actualType.Rank() == 0) { + if (actualType.Rank() == 0 && !actualIsAssumedRank) { evaluate::DesignatorFolder folder{ context.foldingContext(), /*getLastComponent=*/true}; if (auto actualOffset{folder.FoldDesignator(actual)}) { @@ -602,7 +616,18 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, characteristics::DummyDataObject::Attr::DeducedFromActual)) { if (auto dummySize{evaluate::ToInt64(evaluate::Fold( foldingContext, evaluate::GetSize(dummy.type.shape())))}) { - if (actualRank == 0 && !actualIsAssumedRank) { + if (actualIsAssumedRank) { + if (!context.languageFeatures().IsEnabled( + common::LanguageFeature::AssumedRankPassedToNonAssumedRank)) { + messages.Say( + "Assumed-rank array may not be associated with a dummy argument that is not assumed-rank"_err_en_US); + } else { + context.Warn( + common::LanguageFeature::AssumedRankPassedToNonAssumedRank, + messages.at(), + "Assumed-rank array should not be associated with a dummy argument that is not assumed-rank"_port_en_US); + } + } else if (actualRank == 0) { if (evaluate::IsArrayElement(actual)) { // Actual argument is a scalar array element evaluate::DesignatorFolder folder{ @@ -643,7 +668,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, } } } - } else { // actualRank > 0 || actualIsAssumedRank + } else { if (auto actualSize{evaluate::ToInt64(evaluate::Fold( foldingContext, evaluate::GetSize(actualType.shape())))}; actualSize && *actualSize < *dummySize) { diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp index eaf1d52a9fc1a8bed0562e8e20cba686e301efa5..79b7a26ef222f84b0f6fb23cd85142b01047daaf 100644 --- a/flang/lib/Semantics/check-cuda.cpp +++ b/flang/lib/Semantics/check-cuda.cpp @@ -91,6 +91,37 @@ struct DeviceExprChecker } }; +struct FindHostArray + : public evaluate::AnyTraverse { + using Result = const Symbol *; + using Base = evaluate::AnyTraverse; + FindHostArray() : Base(*this) {} + using Base::operator(); + Result operator()(const evaluate::Component &x) const { + const Symbol &symbol{x.GetLastSymbol()}; + if (IsAllocatableOrPointer(symbol)) { + if (Result hostArray{(*this)(symbol)}) { + return hostArray; + } + } + return (*this)(x.base()); + } + Result operator()(const Symbol &symbol) const { + if (const auto *details{ + symbol.GetUltimate().detailsIf()}) { + if (details->IsArray() && + (!details->cudaDataAttr() || + (details->cudaDataAttr() && + *details->cudaDataAttr() != common::CUDADataAttr::Device && + *details->cudaDataAttr() != common::CUDADataAttr::Managed && + *details->cudaDataAttr() != common::CUDADataAttr::Unified))) { + return &symbol; + } + } + return nullptr; + } +}; + template static MaybeMsg CheckUnwrappedExpr(const A &x) { if (const auto *expr{parser::Unwrap(x)}) { return DeviceExprChecker{}(expr->typedExpr); @@ -306,22 +337,11 @@ private: } } template - void ErrorIfHostSymbol(const A &expr, const parser::CharBlock &source) { - for (const Symbol &sym : CollectCudaSymbols(expr)) { - if (const auto *details = - sym.GetUltimate().detailsIf()) { - if (details->IsArray() && - (!details->cudaDataAttr() || - (details->cudaDataAttr() && - *details->cudaDataAttr() != common::CUDADataAttr::Device && - *details->cudaDataAttr() != common::CUDADataAttr::Managed && - *details->cudaDataAttr() != - common::CUDADataAttr::Unified))) { - context_.Say(source, - "Host array '%s' cannot be present in CUF kernel"_err_en_US, - sym.name()); - } - } + void ErrorIfHostSymbol(const A &expr, parser::CharBlock source) { + if (const Symbol * hostArray{FindHostArray{}(expr)}) { + context_.Say(source, + "Host array '%s' cannot be present in CUF kernel"_err_en_US, + hostArray->name()); } } void Check(const parser::ActionStmt &stmt, const parser::CharBlock &source) { diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 86881225e1e55cd226c88b53aa5b1f200a6cf174..c9656d031b2e173be70badb11b8f6f2fd3b3e482 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -147,7 +147,8 @@ private: void CheckProcedureAssemblyName(const Symbol &symbol); void CheckExplicitSave(const Symbol &); parser::Messages WhyNotInteroperableDerivedType(const Symbol &); - parser::Messages WhyNotInteroperableObject(const Symbol &); + parser::Messages WhyNotInteroperableObject( + const Symbol &, bool allowNonInteroperableType = false); parser::Messages WhyNotInteroperableFunctionResult(const Symbol &); parser::Messages WhyNotInteroperableProcedure(const Symbol &, bool isError); void CheckBindC(const Symbol &); @@ -1109,7 +1110,8 @@ void CheckHelper::CheckPointerInitialization(const Symbol &symbol) { if (proc->init() && *proc->init()) { // C1519 - must be nonelemental external or module procedure, // or an unrestricted specific intrinsic function. - const Symbol &ultimate{(*proc->init())->GetUltimate()}; + const Symbol &local{DEREF(*proc->init())}; + const Symbol &ultimate{local.GetUltimate()}; bool checkTarget{true}; if (ultimate.attrs().test(Attr::INTRINSIC)) { if (auto intrinsic{context_.intrinsics().IsSpecificIntrinsicFunction( @@ -1122,11 +1124,12 @@ void CheckHelper::CheckPointerInitialization(const Symbol &symbol) { ultimate.name(), symbol.name()); checkTarget = false; } - } else if ((!ultimate.attrs().test(Attr::EXTERNAL) && - ultimate.owner().kind() != Scope::Kind::Module) || + } else if (!(ultimate.attrs().test(Attr::EXTERNAL) || + ultimate.owner().kind() == Scope::Kind::Module || + ultimate.owner().IsTopLevel()) || IsDummy(ultimate) || IsPointer(ultimate)) { - context_.Say("Procedure pointer '%s' initializer '%s' is neither " - "an external nor a module procedure"_err_en_US, + context_.Say( + "Procedure pointer '%s' initializer '%s' is neither an external nor a module procedure"_err_en_US, symbol.name(), ultimate.name()); checkTarget = false; } else if (IsElementalProcedure(ultimate)) { @@ -3001,7 +3004,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType( return msgs; } -parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) { +parser::Messages CheckHelper::WhyNotInteroperableObject( + const Symbol &symbol, bool allowNonInteroperableType) { parser::Messages msgs; if (examinedByWhyNotInteroperable_.find(symbol) != examinedByWhyNotInteroperable_.end()) { @@ -3037,8 +3041,13 @@ parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) { if (const auto *type{symbol.GetType()}) { const auto *derived{type->AsDerived()}; if (derived && !derived->typeSymbol().attrs().test(Attr::BIND_C)) { - if (!context_.IsEnabled( - common::LanguageFeature::NonBindCInteroperability)) { + if (allowNonInteroperableType) { // portability warning only + evaluate::AttachDeclaration( + context_.Warn(common::UsageWarning::Portability, symbol.name(), + "The derived type of this interoperable object should be BIND(C)"_port_en_US), + derived->typeSymbol()); + } else if (!context_.IsEnabled( + common::LanguageFeature::NonBindCInteroperability)) { msgs.Say(symbol.name(), "The derived type of an interoperable object must be BIND(C)"_err_en_US) .Attach(derived->typeSymbol().name(), "Non-BIND(C) type"_en_US); @@ -3178,7 +3187,13 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure( "A dummy procedure of an interoperable procedure should be BIND(C)"_warn_en_US); } } else if (dummy->has()) { - dummyMsgs = WhyNotInteroperableObject(*dummy); + // Emit only optional portability warnings for non-interoperable + // types when the dummy argument is not VALUE and will be implemented + // on the C side by either a cdesc_t * or a void *. F'2023 18.3.7 (5) + bool allowNonInteroperableType{!dummy->attrs().test(Attr::VALUE) && + (IsDescriptor(*dummy) || IsAssumedType(*dummy))}; + dummyMsgs = + WhyNotInteroperableObject(*dummy, allowNonInteroperableType); } else { CheckBindC(*dummy); } diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h index 2a9cb785a882f80340481b37ff3712e2213df304..91ffda6404c233b66e1838e9cc93ac714b1c3501 100644 --- a/flang/lib/Semantics/check-directive-structure.h +++ b/flang/lib/Semantics/check-directive-structure.h @@ -15,6 +15,8 @@ #include "flang/Common/enum-set.h" #include "flang/Semantics/semantics.h" #include "flang/Semantics/tools.h" +#include "llvm/ADT/iterator_range.h" + #include namespace Fortran::semantics { @@ -292,10 +294,9 @@ protected: return nullptr; } - std::pair - FindClauses(C type) { + llvm::iterator_range FindClauses(C type) { auto it{GetContext().clauseInfo.equal_range(type)}; - return it; + return llvm::make_range(it); } DirectiveContext *GetEnclosingDirContext() { diff --git a/flang/lib/Semantics/check-io.cpp b/flang/lib/Semantics/check-io.cpp index eeeda553d8a467dad4042a3906935d0a74b11323..3c99163c1f134f8c2ea84ee7d701dfbe6dcbe496 100644 --- a/flang/lib/Semantics/check-io.cpp +++ b/flang/lib/Semantics/check-io.cpp @@ -860,6 +860,8 @@ void IoChecker::Leave(const parser::WriteStmt &writeStmt) { void IoChecker::LeaveReadWrite() const { CheckForRequiredSpecifier(IoSpecKind::Unit); // C1211 + CheckForRequiredSpecifier(flags_.test(Flag::InternalUnit), + "UNIT=internal-file", flags_.test(Flag::FmtOrNml), "FMT or NML"); CheckForProhibitedSpecifier(IoSpecKind::Nml, IoSpecKind::Rec); // C1216 CheckForProhibitedSpecifier(IoSpecKind::Nml, IoSpecKind::Fmt); // C1216 CheckForProhibitedSpecifier( diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index a30aba2561c16a256f659d5a3dc1e0b3ff2b10cd..2672a0cc3f835e5bc0b64a31b550936d1efe0180 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -12,6 +12,7 @@ #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" #include "flang/Semantics/tools.h" +#include namespace Fortran::semantics { @@ -337,24 +338,22 @@ void OmpStructureChecker::CheckMultListItems() { semantics::UnorderedSymbolSet listVars; // Aligned clause - auto alignedClauses{FindClauses(llvm::omp::Clause::OMPC_aligned)}; - for (auto itr = alignedClauses.first; itr != alignedClauses.second; ++itr) { - const auto &alignedClause{ - std::get(itr->second->u)}; + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_aligned)) { + const auto &alignedClause{std::get(clause->u)}; const auto &alignedList{std::get<0>(alignedClause.v.t)}; std::list alignedNameList; for (const auto &ompObject : alignedList.v) { if (const auto *name{parser::Unwrap(ompObject)}) { if (name->symbol) { if (FindCommonBlockContaining(*(name->symbol))) { - context_.Say(itr->second->source, + context_.Say(clause->source, "'%s' is a common block name and can not appear in an " "ALIGNED clause"_err_en_US, name->ToString()); } else if (!(IsBuiltinCPtr(*(name->symbol)) || IsAllocatableOrObjectPointer( &name->symbol->GetUltimate()))) { - context_.Say(itr->second->source, + context_.Say(clause->source, "'%s' in ALIGNED clause must be of type C_PTR, POINTER or " "ALLOCATABLE"_err_en_US, name->ToString()); @@ -368,18 +367,16 @@ void OmpStructureChecker::CheckMultListItems() { } } CheckMultipleOccurrence( - listVars, alignedNameList, itr->second->source, "ALIGNED"); + listVars, alignedNameList, clause->source, "ALIGNED"); } // Nontemporal clause - auto nonTemporalClauses{FindClauses(llvm::omp::Clause::OMPC_nontemporal)}; - for (auto itr = nonTemporalClauses.first; itr != nonTemporalClauses.second; - ++itr) { + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_nontemporal)) { const auto &nontempClause{ - std::get(itr->second->u)}; + std::get(clause->u)}; const auto &nontempNameList{nontempClause.v}; CheckMultipleOccurrence( - listVars, nontempNameList, itr->second->source, "NONTEMPORAL"); + listVars, nontempNameList, clause->source, "NONTEMPORAL"); } } @@ -409,7 +406,7 @@ void OmpStructureChecker::HasInvalidDistributeNesting( } else { // `distribute` region has to be strictly nested inside `teams` if (!OmpDirectiveSet{llvm::omp::OMPD_teams, llvm::omp::OMPD_target_teams} - .test(GetContextParent().directive)) { + .test(GetContextParent().directive)) { violation = true; } } @@ -521,8 +518,7 @@ void OmpStructureChecker::CheckHintClause( const Fortran::parser::OmpClauseList>) { ompClause = &clause; } - if (const Fortran::parser::OmpClause::Hint * - hintClause{ + if (const Fortran::parser::OmpClause::Hint *hintClause{ std::get_if(&ompClause->u)}) { std::optional hintValue = GetIntValue(hintClause->v); if (hintValue && *hintValue >= 0) { @@ -687,8 +683,7 @@ void OmpStructureChecker::CheckIteratorRange( } } -void OmpStructureChecker::CheckIteratorModifier( - const parser::OmpIteratorModifier &x) { +void OmpStructureChecker::CheckIteratorModifier(const parser::OmpIterator &x) { // Check if all iterator variables have integer type. for (auto &&iterSpec : x.v) { bool isInteger{true}; @@ -751,62 +746,69 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) { // current context yet. // TODO: Check for declare simd regions. bool eligibleSIMD{false}; - common::visit(Fortran::common::visitors{ - // Allow `!$OMP ORDERED SIMD` - [&](const parser::OpenMPBlockConstruct &c) { - const auto &beginBlockDir{ - std::get(c.t)}; - const auto &beginDir{ - std::get(beginBlockDir.t)}; - if (beginDir.v == llvm::omp::Directive::OMPD_ordered) { - const auto &clauses{ - std::get(beginBlockDir.t)}; - for (const auto &clause : clauses.v) { - if (std::get_if(&clause.u)) { - eligibleSIMD = true; - break; - } - } - } - }, - [&](const parser::OpenMPSimpleStandaloneConstruct &c) { - const auto &dir{ - std::get(c.t)}; - if (dir.v == llvm::omp::Directive::OMPD_ordered) { - const auto &clauses{ - std::get(c.t)}; - for (const auto &clause : clauses.v) { - if (std::get_if(&clause.u)) { - eligibleSIMD = true; - break; - } - } - } - }, - // Allowing SIMD construct - [&](const parser::OpenMPLoopConstruct &c) { - const auto &beginLoopDir{ - std::get(c.t)}; - const auto &beginDir{ - std::get(beginLoopDir.t)}; - if ((beginDir.v == llvm::omp::Directive::OMPD_simd) || - (beginDir.v == llvm::omp::Directive::OMPD_do_simd)) { - eligibleSIMD = true; - } - }, - [&](const parser::OpenMPAtomicConstruct &c) { - // Allow `!$OMP ATOMIC` - eligibleSIMD = true; - }, - [&](const auto &c) {}, - }, + common::visit( + Fortran::common::visitors{ + // Allow `!$OMP ORDERED SIMD` + [&](const parser::OpenMPBlockConstruct &c) { + const auto &beginBlockDir{ + std::get(c.t)}; + const auto &beginDir{ + std::get(beginBlockDir.t)}; + if (beginDir.v == llvm::omp::Directive::OMPD_ordered) { + const auto &clauses{ + std::get(beginBlockDir.t)}; + for (const auto &clause : clauses.v) { + if (std::get_if(&clause.u)) { + eligibleSIMD = true; + break; + } + } + } + }, + [&](const parser::OpenMPStandaloneConstruct &c) { + if (const auto &simpleConstruct = + std::get_if( + &c.u)) { + const auto &dir{std::get( + simpleConstruct->t)}; + if (dir.v == llvm::omp::Directive::OMPD_ordered) { + const auto &clauses{ + std::get(simpleConstruct->t)}; + for (const auto &clause : clauses.v) { + if (std::get_if(&clause.u)) { + eligibleSIMD = true; + break; + } + } + } else if (dir.v == llvm::omp::Directive::OMPD_scan) { + eligibleSIMD = true; + } + } + }, + // Allowing SIMD construct + [&](const parser::OpenMPLoopConstruct &c) { + const auto &beginLoopDir{ + std::get(c.t)}; + const auto &beginDir{ + std::get(beginLoopDir.t)}; + if ((beginDir.v == llvm::omp::Directive::OMPD_simd) || + (beginDir.v == llvm::omp::Directive::OMPD_do_simd)) { + eligibleSIMD = true; + } + }, + [&](const parser::OpenMPAtomicConstruct &c) { + // Allow `!$OMP ATOMIC` + eligibleSIMD = true; + }, + [&](const auto &c) {}, + }, c.u); if (!eligibleSIMD) { context_.Say(parser::FindSourceLocation(c), "The only OpenMP constructs that can be encountered during execution " "of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, " - "the `SIMD` construct and the `ORDERED` construct with the `SIMD` " - "clause."_err_en_US); + "the `SIMD` construct, the `SCAN` construct and the `ORDERED` " + "construct with the `SIMD` clause."_err_en_US); } } @@ -970,6 +972,49 @@ void OmpStructureChecker::CheckDistLinear( } void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) { + const auto &beginLoopDir{std::get(x.t)}; + const auto &clauseList{std::get(beginLoopDir.t)}; + + // A few semantic checks for InScan reduction are performed below as SCAN + // constructs inside LOOP may add the relevant information. Scan reduction is + // supported only in loop constructs, so same checks are not applicable to + // other directives. + for (const auto &clause : clauseList.v) { + if (const auto *reductionClause{ + std::get_if(&clause.u)}) { + const auto &maybeModifier{ + std::get>(reductionClause->v.t)}; + if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { + const auto &objectList{ + std::get(reductionClause->v.t)}; + auto checkReductionSymbolInScan = [&](const parser::Name *name) { + if (auto &symbol = name->symbol) { + if (!symbol->test(Symbol::Flag::OmpInclusiveScan) && + !symbol->test(Symbol::Flag::OmpExclusiveScan)) { + context_.Say(name->source, + "List item %s must appear in EXCLUSIVE or " + "INCLUSIVE clause of an " + "enclosed SCAN directive"_err_en_US, + name->ToString()); + } + } + }; + for (const auto &ompObj : objectList.v) { + common::visit( + common::visitors{ + [&](const parser::Designator &designator) { + if (const auto *name{semantics::getDesignatorNameIfDataRef( + designator)}) { + checkReductionSymbolInScan(name); + } + }, + [&](const auto &name) { checkReductionSymbolInScan(&name); }, + }, + ompObj.u); + } + } + } + } if (llvm::omp::allSimdSet.test(GetContext().directive)) { ExitDirectiveNest(SIMDNest); } @@ -1477,6 +1522,21 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) { } } +void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) { + const auto &dir{std::get(x.t)}; + PushContextAndClauseSets( + dir.source, llvm::omp::Directive::OMPD_declare_mapper); + const auto &spec{std::get(x.t)}; + const auto &type = std::get(spec.t); + if (!std::get_if(&type.u)) { + context_.Say(dir.source, "Type is not a derived type"_err_en_US); + } +} + +void OmpStructureChecker::Leave(const parser::OpenMPDeclareMapperConstruct &) { + dirContext_.pop_back(); +} + void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) { const auto &dir{std::get(x.t)}; PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target); @@ -1642,19 +1702,32 @@ void OmpStructureChecker::Leave(const parser::OpenMPAllocatorsConstruct &x) { dirContext_.pop_back(); } +void OmpStructureChecker::CheckScan( + const parser::OpenMPSimpleStandaloneConstruct &x) { + if (std::get(x.t).v.size() != 1) { + context_.Say(x.source, + "Exactly one of EXCLUSIVE or INCLUSIVE clause is expected"_err_en_US); + } + if (!CurrentDirectiveIsNested() || + !llvm::omp::scanParentAllowedSet.test(GetContextParent().directive)) { + context_.Say(x.source, + "Orphaned SCAN directives are prohibited; perhaps you forgot " + "to enclose the directive in to a WORKSHARING LOOP, a WORKSHARING " + "LOOP SIMD or a SIMD directive."_err_en_US); + } +} + void OmpStructureChecker::CheckBarrierNesting( const parser::OpenMPSimpleStandaloneConstruct &x) { // A barrier region may not be `closely nested` inside a worksharing, loop, // task, taskloop, critical, ordered, atomic, or master region. // TODO: Expand the check to include `LOOP` construct as well when it is // supported. - if (GetContext().directive == llvm::omp::Directive::OMPD_barrier) { - if (IsCloselyNestedRegion(llvm::omp::nestedBarrierErrSet)) { - context_.Say(parser::FindSourceLocation(x), - "`BARRIER` region may not be closely nested inside of `WORKSHARING`, " - "`LOOP`, `TASK`, `TASKLOOP`," - "`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region."_err_en_US); - } + if (IsCloselyNestedRegion(llvm::omp::nestedBarrierErrSet)) { + context_.Say(parser::FindSourceLocation(x), + "`BARRIER` region may not be closely nested inside of `WORKSHARING`, " + "`LOOP`, `TASK`, `TASKLOOP`," + "`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region."_err_en_US); } } @@ -1688,21 +1761,18 @@ void OmpStructureChecker::ChecksOnOrderedAsStandalone() { }}; // Visit the DEPEND and DOACROSS clauses. - auto depClauses{FindClauses(llvm::omp::Clause::OMPC_depend)}; - for (auto itr{depClauses.first}; itr != depClauses.second; ++itr) { - const auto &dependClause{ - std::get(itr->second->u)}; + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_depend)) { + const auto &dependClause{std::get(clause->u)}; if (auto *doAcross{std::get_if(&dependClause.v.u)}) { - visitDoacross(*doAcross, itr->second->source); + visitDoacross(*doAcross, clause->source); } else { - context_.Say(itr->second->source, + context_.Say(clause->source, "Only SINK or SOURCE dependence types are allowed when ORDERED construct is a standalone construct with no ORDERED region"_err_en_US); } } - auto doaClauses{FindClauses(llvm::omp::Clause::OMPC_doacross)}; - for (auto itr{doaClauses.first}; itr != doaClauses.second; ++itr) { - auto &doaClause{std::get(itr->second->u)}; - visitDoacross(doaClause.v.v, itr->second->source); + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_doacross)) { + auto &doaClause{std::get(clause->u)}; + visitDoacross(doaClause.v.v, clause->source); } bool isNestedInDoOrderedWithPara{false}; @@ -1741,17 +1811,15 @@ void OmpStructureChecker::CheckOrderedDependClause( } } }}; - auto depClauses{FindClauses(llvm::omp::Clause::OMPC_depend)}; - for (auto itr{depClauses.first}; itr != depClauses.second; ++itr) { - auto &dependClause{std::get(itr->second->u)}; + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_depend)) { + auto &dependClause{std::get(clause->u)}; if (auto *doAcross{std::get_if(&dependClause.v.u)}) { - visitDoacross(*doAcross, itr->second->source); + visitDoacross(*doAcross, clause->source); } } - auto doaClauses = FindClauses(llvm::omp::Clause::OMPC_doacross); - for (auto itr{doaClauses.first}; itr != doaClauses.second; ++itr) { - auto &doaClause{std::get(itr->second->u)}; - visitDoacross(doaClause.v.v, itr->second->source); + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_doacross)) { + auto &doaClause{std::get(clause->u)}; + visitDoacross(doaClause.v.v, clause->source); } } @@ -1790,21 +1858,21 @@ void OmpStructureChecker::CheckTargetUpdate() { } void OmpStructureChecker::CheckTaskDependenceType( - const parser::OmpTaskDependenceType::Type &x) { + const parser::OmpTaskDependenceType::Value &x) { // Common checks for task-dependence-type (DEPEND and UPDATE clauses). unsigned version{context_.langOptions().OpenMPVersion}; unsigned since{0}; switch (x) { - case parser::OmpTaskDependenceType::Type::In: - case parser::OmpTaskDependenceType::Type::Out: - case parser::OmpTaskDependenceType::Type::Inout: + case parser::OmpTaskDependenceType::Value::In: + case parser::OmpTaskDependenceType::Value::Out: + case parser::OmpTaskDependenceType::Value::Inout: break; - case parser::OmpTaskDependenceType::Type::Mutexinoutset: - case parser::OmpTaskDependenceType::Type::Depobj: + case parser::OmpTaskDependenceType::Value::Mutexinoutset: + case parser::OmpTaskDependenceType::Value::Depobj: since = 50; break; - case parser::OmpTaskDependenceType::Type::Inoutset: + case parser::OmpTaskDependenceType::Value::Inoutset: since = 52; break; } @@ -1819,14 +1887,14 @@ void OmpStructureChecker::CheckTaskDependenceType( } void OmpStructureChecker::CheckDependenceType( - const parser::OmpDependenceType::Type &x) { + const parser::OmpDependenceType::Value &x) { // Common checks for dependence-type (DEPEND and UPDATE clauses). unsigned version{context_.langOptions().OpenMPVersion}; unsigned deprecatedIn{~0u}; switch (x) { - case parser::OmpDependenceType::Type::Source: - case parser::OmpDependenceType::Type::Sink: + case parser::OmpDependenceType::Value::Source: + case parser::OmpDependenceType::Value::Sink: deprecatedIn = 52; break; } @@ -1843,7 +1911,16 @@ void OmpStructureChecker::Enter( const parser::OpenMPSimpleStandaloneConstruct &x) { const auto &dir{std::get(x.t)}; PushContextAndClauseSets(dir.source, dir.v); - CheckBarrierNesting(x); + switch (dir.v) { + case llvm::omp::Directive::OMPD_barrier: + CheckBarrierNesting(x); + break; + case llvm::omp::Directive::OMPD_scan: + CheckScan(x); + break; + default: + break; + } } void OmpStructureChecker::Leave( @@ -2652,7 +2729,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) { break; } - if (const parser::OmpObjectList * objList{GetOmpObjectList(x)}) { + if (const parser::OmpObjectList *objList{GetOmpObjectList(x)}) { SymbolSourceMap symbols; GetSymbolsInObjectList(*objList, symbols); for (const auto &[sym, source] : symbols) { @@ -2682,8 +2759,8 @@ CHECK_SIMPLE_CLAUSE(Full, OMPC_full) CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize) CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) CHECK_SIMPLE_CLAUSE(Holds, OMPC_holds) -CHECK_SIMPLE_CLAUSE(InReduction, OMPC_in_reduction) CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive) +CHECK_SIMPLE_CLAUSE(InReduction, OMPC_in_reduction) CHECK_SIMPLE_CLAUSE(Match, OMPC_match) CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal) CHECK_SIMPLE_CLAUSE(NumTasks, OMPC_num_tasks) @@ -2800,13 +2877,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { if (CheckReductionOperators(x)) { CheckReductionTypeList(x); } - CheckReductionModifier(x); + if (const auto &maybeModifier{ + std::get>(x.v.t)}) { + const ReductionModifier modifier{*maybeModifier}; + CheckReductionModifier(modifier); + } } bool OmpStructureChecker::CheckReductionOperators( const parser::OmpClause::Reduction &x) { - const auto &definedOp{std::get(x.v.t)}; + const auto &definedOp{std::get(x.v.t)}; bool ok = false; common::visit( common::visitors{ @@ -2843,6 +2924,7 @@ bool OmpStructureChecker::CheckReductionOperators( return ok; } + bool OmpStructureChecker::CheckIntrinsicOperator( const parser::DefinedOperator::IntrinsicOperator &op) { @@ -2870,7 +2952,7 @@ bool OmpStructureChecker::CheckIntrinsicOperator( static bool IsReductionAllowedForType( const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) { - const auto &definedOp{std::get(x.v.t)}; + const auto &definedOp{std::get(x.v.t)}; // TODO: user defined reduction operators. Just allow everything for now. bool ok{true}; @@ -2977,14 +3059,11 @@ void OmpStructureChecker::CheckReductionTypeList( } void OmpStructureChecker::CheckReductionModifier( - const parser::OmpClause::Reduction &x) { - using ReductionModifier = parser::OmpReductionClause::ReductionModifier; - const auto &maybeModifier{std::get>(x.v.t)}; - if (!maybeModifier || *maybeModifier == ReductionModifier::Default) { - // No modifier, or the default one is always ok. + const ReductionModifier &modifier) { + if (modifier == ReductionModifier::Default) { + // The default one is always ok. return; } - ReductionModifier modifier{*maybeModifier}; const DirectiveContext &dirCtx{GetContext()}; if (dirCtx.directive == llvm::omp::Directive::OMPD_loop) { // [5.2:257:33-34] @@ -3015,15 +3094,10 @@ void OmpStructureChecker::CheckReductionModifier( // or "simd" directive. // The worksharing-loop directives are OMPD_do and OMPD_for. Only the // former is allowed in Fortran. - switch (dirCtx.directive) { - case llvm::omp::Directive::OMPD_do: // worksharing-loop - case llvm::omp::Directive::OMPD_do_simd: // worksharing-loop simd - case llvm::omp::Directive::OMPD_simd: // "simd" - break; - default: + if (!llvm::omp::scanParentAllowedSet.test(dirCtx.directive)) { context_.Say(GetContext().clauseSource, "Modifier 'INSCAN' on REDUCTION clause is only allowed with " - "worksharing-loop, worksharing-loop simd, " + "WORKSHARING LOOP, WORKSHARING LOOP SIMD, " "or SIMD directive"_err_en_US); } } else { @@ -3261,7 +3335,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) { void OmpStructureChecker::CheckIsLoopIvPartOfClause( llvmOmpClause clause, const parser::OmpObjectList &ompObjectList) { for (const auto &ompObject : ompObjectList.v) { - if (const parser::Name * name{parser::Unwrap(ompObject)}) { + if (const parser::Name *name{parser::Unwrap(ompObject)}) { if (name->symbol == GetContext().loopIV) { context_.Say(name->source, "DO iteration variable %s is not allowed in %s clause."_err_en_US, @@ -3282,14 +3356,17 @@ void OmpStructureChecker::Leave(const parser::OmpAtomicRead &) { CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_read, {llvm::omp::Clause::OMPC_release, llvm::omp::Clause::OMPC_acq_rel}); } + void OmpStructureChecker::Leave(const parser::OmpAtomicWrite &) { CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_write, {llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_acq_rel}); } + void OmpStructureChecker::Leave(const parser::OmpAtomicUpdate &) { CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_update, {llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_acq_rel}); } + // OmpAtomic node represents atomic directive without atomic-clause. // atomic-clause - READ,WRITE,UPDATE,CAPTURE. void OmpStructureChecker::Leave(const parser::OmpAtomic &) { @@ -3302,6 +3379,7 @@ void OmpStructureChecker::Leave(const parser::OmpAtomic &) { "Clause ACQ_REL is not allowed on the ATOMIC directive"_err_en_US); } } + // Restrictions specific to each clause are implemented apart from the // generalized restrictions. void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) { @@ -3313,15 +3391,48 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) { } // 2.8.1 TODO: list-item attribute check } + void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_defaultmap); + unsigned version{context_.langOptions().OpenMPVersion}; + using ImplicitBehavior = parser::OmpDefaultmapClause::ImplicitBehavior; + auto behavior{std::get(x.v.t)}; + if (version <= 45) { + if (behavior != ImplicitBehavior::Tofrom) { + context_.Say(GetContext().clauseSource, + "%s is not allowed in %s, %s"_warn_en_US, + parser::ToUpperCaseLetters( + parser::OmpDefaultmapClause::EnumToString(behavior)), + ThisVersion(version), TryVersion(50)); + } + } using VariableCategory = parser::OmpDefaultmapClause::VariableCategory; - if (!std::get>(x.v.t)) { - context_.Say(GetContext().clauseSource, - "The argument TOFROM:SCALAR must be specified on the DEFAULTMAP " - "clause"_err_en_US); + auto maybeCategory{std::get>(x.v.t)}; + if (!maybeCategory) { + if (version <= 45) { + context_.Say(GetContext().clauseSource, + "The DEFAULTMAP clause requires a variable-category SCALAR in %s, %s"_warn_en_US, + ThisVersion(version), TryVersion(50)); + } + } else { + VariableCategory category{*maybeCategory}; + unsigned tryVersion{0}; + if (version <= 45 && category != VariableCategory::Scalar) { + tryVersion = 50; + } + if (version < 52 && category == VariableCategory::All) { + tryVersion = 52; + } + if (tryVersion) { + context_.Say(GetContext().clauseSource, + "%s is not allowed in %s, %s"_warn_en_US, + parser::ToUpperCaseLetters( + parser::OmpDefaultmapClause::EnumToString(category)), + ThisVersion(version), TryVersion(tryVersion)); + } } } + void OmpStructureChecker::Enter(const parser::OmpClause::If &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_if); using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier; @@ -3396,7 +3507,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_map); using TypeMod = parser::OmpMapClause::TypeModifier; using Type = parser::OmpMapClause::Type; - using IterMod = parser::OmpIteratorModifier; + using IterMod = parser::OmpIterator; unsigned version{context_.langOptions().OpenMPVersion}; if (auto commas{std::get(x.v.t)}; !commas && version >= 52) { @@ -3549,7 +3660,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { if (taskDep) { if (version == 50) { invalidDep = taskDep->GetTaskDepType() == - parser::OmpTaskDependenceType::Type::Depobj; + parser::OmpTaskDependenceType::Value::Depobj; } } else { invalidDep = true; @@ -3596,7 +3707,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { } } } - if (std::get>(taskDep->t)) { + if (std::get>(taskDep->t)) { unsigned allowedInVersion{50}; if (version < allowedInVersion) { context_.Say(GetContext().clauseSource, @@ -3835,7 +3946,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Update &x) { if (version >= 51) { bool invalidDep{false}; if (taskType) { - invalidDep = taskType->v == parser::OmpTaskDependenceType::Type::Depobj; + invalidDep = + taskType->v == parser::OmpTaskDependenceType::Value::Depobj; } else { invalidDep = true; } @@ -3853,19 +3965,16 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) { SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); semantics::UnorderedSymbolSet listVars; - auto useDevicePtrClauses{FindClauses(llvm::omp::Clause::OMPC_use_device_ptr)}; - for (auto itr = useDevicePtrClauses.first; itr != useDevicePtrClauses.second; - ++itr) { + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_use_device_ptr)) { const auto &useDevicePtrClause{ - std::get(itr->second->u)}; + std::get(clause->u)}; const auto &useDevicePtrList{useDevicePtrClause.v}; std::list useDevicePtrNameList; for (const auto &ompObject : useDevicePtrList.v) { if (const auto *name{parser::Unwrap(ompObject)}) { if (name->symbol) { if (!(IsBuiltinCPtr(*(name->symbol)))) { - context_.Warn(common::UsageWarning::OpenMPUsage, - itr->second->source, + context_.Warn(common::UsageWarning::OpenMPUsage, clause->source, "Use of non-C_PTR type '%s' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead"_warn_en_US, name->ToString()); } else { @@ -3875,7 +3984,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) { } } CheckMultipleOccurrence( - listVars, useDevicePtrNameList, itr->second->source, "USE_DEVICE_PTR"); + listVars, useDevicePtrNameList, clause->source, "USE_DEVICE_PTR"); } } @@ -3885,12 +3994,10 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) { SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); semantics::UnorderedSymbolSet listVars; - auto useDeviceAddrClauses{ - FindClauses(llvm::omp::Clause::OMPC_use_device_addr)}; - for (auto itr = useDeviceAddrClauses.first; - itr != useDeviceAddrClauses.second; ++itr) { + for (auto [_, clause] : + FindClauses(llvm::omp::Clause::OMPC_use_device_addr)) { const auto &useDeviceAddrClause{ - std::get(itr->second->u)}; + std::get(clause->u)}; const auto &useDeviceAddrList{useDeviceAddrClause.v}; std::list useDeviceAddrNameList; for (const auto &ompObject : useDeviceAddrList.v) { @@ -3900,8 +4007,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) { } } } - CheckMultipleOccurrence(listVars, useDeviceAddrNameList, - itr->second->source, "USE_DEVICE_ADDR"); + CheckMultipleOccurrence( + listVars, useDeviceAddrNameList, clause->source, "USE_DEVICE_ADDR"); } } @@ -3910,26 +4017,24 @@ void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) { SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); semantics::UnorderedSymbolSet listVars; - auto isDevicePtrClauses{FindClauses(llvm::omp::Clause::OMPC_is_device_ptr)}; - for (auto itr = isDevicePtrClauses.first; itr != isDevicePtrClauses.second; - ++itr) { + for (auto [_, clause] : FindClauses(llvm::omp::Clause::OMPC_is_device_ptr)) { const auto &isDevicePtrClause{ - std::get(itr->second->u)}; + std::get(clause->u)}; const auto &isDevicePtrList{isDevicePtrClause.v}; SymbolSourceMap currSymbols; GetSymbolsInObjectList(isDevicePtrList, currSymbols); for (auto &[symbol, source] : currSymbols) { if (!(IsBuiltinCPtr(*symbol))) { - context_.Say(itr->second->source, + context_.Say(clause->source, "Variable '%s' in IS_DEVICE_PTR clause must be of type C_PTR"_err_en_US, source.ToString()); } else if (!(IsDummy(*symbol))) { - context_.Warn(common::UsageWarning::OpenMPUsage, itr->second->source, + context_.Warn(common::UsageWarning::OpenMPUsage, clause->source, "Variable '%s' in IS_DEVICE_PTR clause must be a dummy argument. " "This semantic check is deprecated from OpenMP 5.2 and later."_warn_en_US, source.ToString()); } else if (IsAllocatableOrPointer(*symbol) || IsValue(*symbol)) { - context_.Warn(common::UsageWarning::OpenMPUsage, itr->second->source, + context_.Warn(common::UsageWarning::OpenMPUsage, clause->source, "Variable '%s' in IS_DEVICE_PTR clause must be a dummy argument " "that does not have the ALLOCATABLE, POINTER or VALUE attribute. " "This semantic check is deprecated from OpenMP 5.2 and later."_warn_en_US, @@ -3944,12 +4049,10 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) { SymbolSourceMap currSymbols; GetSymbolsInObjectList(x.v, currSymbols); semantics::UnorderedSymbolSet listVars; - auto hasDeviceAddrClauses{ - FindClauses(llvm::omp::Clause::OMPC_has_device_addr)}; - for (auto itr = hasDeviceAddrClauses.first; - itr != hasDeviceAddrClauses.second; ++itr) { + for (auto [_, clause] : + FindClauses(llvm::omp::Clause::OMPC_has_device_addr)) { const auto &hasDeviceAddrClause{ - std::get(itr->second->u)}; + std::get(clause->u)}; const auto &hasDeviceAddrList{hasDeviceAddrClause.v}; std::list hasDeviceAddrNameList; for (const auto &ompObject : hasDeviceAddrList.v) { @@ -3979,7 +4082,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_from); unsigned version{context_.langOptions().OpenMPVersion}; using ExpMod = parser::OmpFromClause::Expectation; - using IterMod = parser::OmpIteratorModifier; + using IterMod = parser::OmpIterator; if (auto &expMod{std::get>>(x.v.t)}) { unsigned allowedInVersion{51}; @@ -4043,7 +4146,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) { } assert(GetContext().directive == llvm::omp::OMPD_target_update); using ExpMod = parser::OmpFromClause::Expectation; - using IterMod = parser::OmpIteratorModifier; + using IterMod = parser::OmpIterator; if (auto &expMod{std::get>>(x.v.t)}) { unsigned allowedInVersion{51}; @@ -4233,7 +4336,7 @@ void OmpStructureChecker::CheckPrivateSymbolsInOuterCxt( auto enclosingClauseSet{dirIter->second.second}; if (auto *enclosingContext{GetEnclosingContextWithDir(enclosingDir)}) { for (auto it{enclosingContext->clauseInfo.begin()}; - it != enclosingContext->clauseInfo.end(); ++it) { + it != enclosingContext->clauseInfo.end(); ++it) { if (enclosingClauseSet.test(it->first)) { if (const auto *ompObjectList{GetOmpObjectList(*it->second)}) { GetSymbolsInObjectList(*ompObjectList, enclosingSymbols); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 8c13dd20d1e3996f35f7733dc5aaad9873c102d1..df21ebac0f6d76a758767d3d58ac489c4210020e 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -70,6 +70,7 @@ public: ) { } using llvmOmpClause = const llvm::omp::Clause; + using ReductionModifier = parser::OmpReductionClause::ReductionModifier; void Enter(const parser::OpenMPConstruct &); void Leave(const parser::OpenMPConstruct &); @@ -93,6 +94,8 @@ public: void Leave(const parser::OpenMPDeclareSimdConstruct &); void Enter(const parser::OpenMPDeclarativeAllocate &); void Leave(const parser::OpenMPDeclarativeAllocate &); + void Enter(const parser::OpenMPDeclareMapperConstruct &); + void Leave(const parser::OpenMPDeclareMapperConstruct &); void Enter(const parser::OpenMPDeclareTargetConstruct &); void Leave(const parser::OpenMPDeclareTargetConstruct &); void Enter(const parser::OpenMPDepobjConstruct &); @@ -199,7 +202,7 @@ private: void CheckWorkshareBlockStmts(const parser::Block &, parser::CharBlock); void CheckIteratorRange(const parser::OmpIteratorSpecifier &x); - void CheckIteratorModifier(const parser::OmpIteratorModifier &x); + void CheckIteratorModifier(const parser::OmpIterator &x); void CheckLoopItrVariableIsInt(const parser::OpenMPLoopConstruct &x); void CheckDoWhile(const parser::OpenMPLoopConstruct &x); void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x); @@ -215,8 +218,8 @@ private: void CheckSIMDNest(const parser::OpenMPConstruct &x); void CheckTargetNest(const parser::OpenMPConstruct &x); void CheckTargetUpdate(); - void CheckDependenceType(const parser::OmpDependenceType::Type &x); - void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Type &x); + void CheckDependenceType(const parser::OmpDependenceType::Value &x); + void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x); void CheckCancellationNest( const parser::CharBlock &source, const parser::OmpCancelType::Type &type); std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x); @@ -224,10 +227,11 @@ private: bool CheckIntrinsicOperator( const parser::DefinedOperator::IntrinsicOperator &); void CheckReductionTypeList(const parser::OmpClause::Reduction &); - void CheckReductionModifier(const parser::OmpClause::Reduction &); + void CheckReductionModifier(const ReductionModifier &); void CheckMasterNesting(const parser::OpenMPBlockConstruct &x); void ChecksOnOrderedAsBlock(); void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x); + void CheckScan(const parser::OpenMPSimpleStandaloneConstruct &x); void ChecksOnOrderedAsStandalone(); void CheckOrderedDependClause(std::optional orderedValue); void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList); diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70ca988cddce599ee9b1a2d1b02161b3ce9089b0 --- /dev/null +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -0,0 +1,146 @@ +//===-- flang/lib/Semantics/openmp-modifiers.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 "flang/Semantics/openmp-modifiers.h" + +#include "flang/Parser/parse-tree.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Frontend/OpenMP/OMP.h" + +#include +#include +#include + +namespace Fortran::semantics { +using namespace llvm::omp; + +/// Find the highest version that exists as a key in the given map, +/// and is less than or equal to `version`. +/// Account for "version" not being a value from getOpenMPVersions(). +template +static unsigned findVersion( + unsigned version, const std::map &map) { + llvm::ArrayRef versions{llvm::omp::getOpenMPVersions()}; + assert(!versions.empty() && "getOpenMPVersions returned empty list"); + version = std::clamp(version, versions.front(), versions.back()); + + // std::map is sorted with respect to keys, by default in the ascending + // order. + unsigned found{0}; + for (auto &[v, _] : map) { + if (v <= version) { + found = v; + } else { + break; + } + } + + assert(found != 0 && "cannot locate entry for version in map"); + return found; +} + +const OmpProperties &OmpModifierDescriptor::props(unsigned version) const { + return props_.at(findVersion(version, props_)); +} + +const OmpClauses &OmpModifierDescriptor::clauses(unsigned version) const { + return clauses_.at(findVersion(version, clauses_)); +} + +// Note: The intent for these functions is to have them be automatically- +// generated in the future. + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"dependence-type", + /*props=*/ + { + {45, {OmpProperty::Required, OmpProperty::Ultimate}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_depend}}, + {51, {Clause::OMPC_depend, Clause::OMPC_update}}, + {52, {Clause::OMPC_doacross}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"iterator", + /*props=*/ + { + {50, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {50, {Clause::OMPC_affinity, Clause::OMPC_depend}}, + {51, + {Clause::OMPC_affinity, Clause::OMPC_depend, Clause::OMPC_from, + Clause::OMPC_map, Clause::OMPC_to}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"linear-modifier", + /*props=*/ + { + {45, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_linear}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor & +OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"reduction-identifier", + /*props=*/ + { + {45, {OmpProperty::Required, OmpProperty::Ultimate}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_reduction}}, + {50, + {Clause::OMPC_in_reduction, Clause::OMPC_reduction, + Clause::OMPC_task_reduction}}, + }, + }; + return desc; +} + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"task-dependence-type", + /*props=*/ + { + {52, {OmpProperty::Required, OmpProperty::Ultimate}}, + }, + /*clauses=*/ + { + {52, {Clause::OMPC_depend, Clause::OMPC_update}}, + }, + }; + return desc; +} +} // namespace Fortran::semantics diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 83d666283a48c8b124d19f97ed289acc731234ed..80e238f3476ac80e3e46e15ed1c6938438e3e1b8 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -431,6 +431,9 @@ public: bool Pre(const parser::OpenMPDeclareTargetConstruct &); void Post(const parser::OpenMPDeclareTargetConstruct &) { PopContext(); } + bool Pre(const parser::OpenMPDeclareMapperConstruct &); + void Post(const parser::OpenMPDeclareMapperConstruct &) { PopContext(); } + bool Pre(const parser::OpenMPThreadprivate &); void Post(const parser::OpenMPThreadprivate &) { PopContext(); } @@ -458,6 +461,14 @@ public: } // 2.15.3 Data-Sharing Attribute Clauses + bool Pre(const parser::OmpClause::Inclusive &x) { + ResolveOmpObjectList(x.v, Symbol::Flag::OmpInclusiveScan); + return false; + } + bool Pre(const parser::OmpClause::Exclusive &x) { + ResolveOmpObjectList(x.v, Symbol::Flag::OmpExclusiveScan); + return false; + } void Post(const parser::OmpDefaultClause &); bool Pre(const parser::OmpClause::Shared &x) { ResolveOmpObjectList(x.v, Symbol::Flag::OmpShared); @@ -507,8 +518,8 @@ public: } bool Pre(const parser::OmpClause::Reduction &x) { - const parser::OmpReductionOperator &opr{ - std::get(x.v.t)}; + const parser::OmpReductionIdentifier &opr{ + std::get(x.v.t)}; auto createDummyProcSymbol = [&](const parser::Name *name) { // If name resolution failed, create a dummy symbol const auto namePair{ @@ -538,6 +549,12 @@ public: } const auto &objList{std::get(x.v.t)}; ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction); + using ReductionModifier = parser::OmpReductionClause::ReductionModifier; + const auto &maybeModifier{ + std::get>(x.v.t)}; + if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { + ResolveOmpObjectList(objList, Symbol::Flag::OmpInScanReduction); + } return false; } @@ -692,8 +709,9 @@ private: Symbol::Flag::OmpUseDevicePtr, Symbol::Flag::OmpUseDeviceAddr, Symbol::Flag::OmpIsDevicePtr, Symbol::Flag::OmpHasDeviceAddr}; - Symbol::Flags ompFlagsRequireMark{ - Symbol::Flag::OmpThreadprivate, Symbol::Flag::OmpDeclareTarget}; + Symbol::Flags ompFlagsRequireMark{Symbol::Flag::OmpThreadprivate, + Symbol::Flag::OmpDeclareTarget, Symbol::Flag::OmpExclusiveScan, + Symbol::Flag::OmpInclusiveScan, Symbol::Flag::OmpInScanReduction}; Symbol::Flags dataCopyingAttributeFlags{ Symbol::Flag::OmpCopyIn, Symbol::Flag::OmpCopyPrivate}; @@ -1626,6 +1644,7 @@ bool OmpAttributeVisitor::Pre( switch (standaloneDir.v) { case llvm::omp::Directive::OMPD_barrier: case llvm::omp::Directive::OMPD_ordered: + case llvm::omp::Directive::OMPD_scan: case llvm::omp::Directive::OMPD_target_enter_data: case llvm::omp::Directive::OMPD_target_exit_data: case llvm::omp::Directive::OMPD_target_update: @@ -1953,6 +1972,11 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) { return true; } +bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) { + PushContext(x.source, llvm::omp::Directive::OMPD_declare_mapper); + return true; +} + bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) { PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate); const auto &list{std::get(x.t)}; @@ -2429,6 +2453,16 @@ void OmpAttributeVisitor::ResolveOmpObject( name->ToString()); } } + if (ompFlag == Symbol::Flag::OmpInclusiveScan || + ompFlag == Symbol::Flag::OmpExclusiveScan) { + if (!symbol->test(Symbol::Flag::OmpInScanReduction)) { + context_.Say(name->source, + "List item %s must appear in REDUCTION clause " + "with the INSCAN modifier of the parent " + "directive"_err_en_US, + name->ToString()); + } + } if (GetContext().directive == llvm::omp::Directive::OMPD_target_data) { checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr, diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index e0a8246ebc752ebd916e37bcd7f5d156d366337f..929d35a4717dcb447d989a82a18e58fbf81c6b6b 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1468,6 +1468,11 @@ public: AddOmpSourceRange(x.source); return true; } + + bool Pre(const parser::OpenMPDeclareMapperConstruct &); + + bool Pre(const parser::OmpMapClause &); + void Post(const parser::OmpBeginLoopDirective &) { messageHandler().set_currStmtSource(std::nullopt); } @@ -1605,6 +1610,64 @@ void OmpVisitor::Post(const parser::OpenMPBlockConstruct &x) { } } +// This "manually" walks the tree of the construct, because we need +// to resolve the type before the map clauses are processed - when +// just following the natural flow, the map clauses gets processed before +// the type has been fully processed. +bool OmpVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) { + AddOmpSourceRange(x.source); + BeginDeclTypeSpec(); + const auto &spec{std::get(x.t)}; + Symbol *mapperSym{nullptr}; + if (const auto &mapperName{std::get>(spec.t)}) { + mapperSym = + &MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); + mapperName->symbol = mapperSym; + } else { + const parser::CharBlock defaultName{"default", 7}; + mapperSym = &MakeSymbol( + defaultName, Attrs{}, MiscDetails{MiscDetails::Kind::ConstructName}); + } + + PushScope(Scope::Kind::OtherConstruct, nullptr); + Walk(std::get(spec.t)); + const auto &varName{std::get(spec.t)}; + DeclareObjectEntity(varName); + + Walk(std::get(x.t)); + + EndDeclTypeSpec(); + PopScope(); + return false; +} + +bool OmpVisitor::Pre(const parser::OmpMapClause &x) { + const auto &mid{std::get(x.t)}; + if (const auto &mapperName{mid.v}) { + if (const auto symbol = FindSymbol(currScope(), *mapperName)) { + // TODO: Do we need a specific flag or type here, to distinghuish against + // other ConstructName things? Leaving this for the full implementation + // of mapper lowering. + auto *misc{symbol->detailsIf()}; + if (!misc || misc->kind() != MiscDetails::Kind::ConstructName) + context().Say(mapperName->source, + "Name '%s' should be a mapper name"_err_en_US, mapperName->source); + else + mapperName->symbol = symbol; + } else { + mapperName->symbol = &MakeSymbol( + *mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); + // TODO: When completing the implementation, we probably want to error if + // the symbol is not declared, but right now, testing that the TODO for + // OmpMapclause happens is obscured by the TODO for declare mapper, so + // leaving this out. Remove the above line once the declare mapper is + // implemented. context().Say(mapperName->source, "'%s' not + // declared"_err_en_US, mapperName->source); + } + } + return true; +} + // Walk the parse tree and resolve names to symbols. class ResolveNamesVisitor : public virtual ScopeHandler, public ModuleVisitor, @@ -4787,10 +4850,13 @@ void DeclarationVisitor::Post(const parser::EntityDecl &x) { } else if (attrs.test(Attr::PARAMETER)) { // C882, C883 Say(name, "Missing initialization for parameter '%s'"_err_en_US); } - if (auto *scopeSymbol{currScope().symbol()}) - if (auto *details{scopeSymbol->detailsIf()}) - if (details->isDECStructure()) + if (auto *scopeSymbol{currScope().symbol()}) { + if (auto *details{scopeSymbol->detailsIf()}) { + if (details->isDECStructure()) { details->add_component(symbol); + } + } + } } void DeclarationVisitor::Post(const parser::PointerDecl &x) { @@ -7660,10 +7726,54 @@ public: --blockDepth_; PopScope(); } + // Note declarations of local names in BLOCK constructs. + // Don't have to worry about INTENT(), VALUE, or OPTIONAL + // (pertinent only to dummy arguments), ASYNCHRONOUS/VOLATILE, + // or accessibility attributes, bool Pre(const parser::EntityDecl &x) { Hide(std::get(x.t)); return true; } + bool Pre(const parser::ObjectDecl &x) { + Hide(std::get(x.t)); + return true; + } + bool Pre(const parser::PointerDecl &x) { + Hide(std::get(x.t)); + return true; + } + bool Pre(const parser::BindEntity &x) { + Hide(std::get(x.t)); + return true; + } + bool Pre(const parser::ContiguousStmt &x) { + for (const parser::Name &name : x.v) { + Hide(name); + } + return true; + } + bool Pre(const parser::DimensionStmt::Declaration &x) { + Hide(std::get(x.t)); + return true; + } + bool Pre(const parser::ExternalStmt &x) { + for (const parser::Name &name : x.v) { + Hide(name); + } + return true; + } + bool Pre(const parser::IntrinsicStmt &x) { + for (const parser::Name &name : x.v) { + Hide(name); + } + return true; + } + bool Pre(const parser::CodimensionStmt &x) { + for (const parser::CodimensionDecl &decl : x.v) { + Hide(std::get(decl.t)); + } + return true; + } void Post(const parser::ImportStmt &x) { if (x.kind == common::ImportKind::None || x.kind == common::ImportKind::Only) { diff --git a/flang/lib/Semantics/unparse-with-symbols.cpp b/flang/lib/Semantics/unparse-with-symbols.cpp index c451f885c06279f8b38fab9f80959405460190bd..02afb89ae57fafd44269808c1fb225c6d90869d9 100644 --- a/flang/lib/Semantics/unparse-with-symbols.cpp +++ b/flang/lib/Semantics/unparse-with-symbols.cpp @@ -53,6 +53,14 @@ public: void Post(const parser::OpenMPThreadprivate &) { currStmt_ = std::nullopt; } void Post(const parser::Name &name); + bool Pre(const parser::OpenMPDeclareMapperConstruct &x) { + currStmt_ = x.source; + return true; + } + void Post(const parser::OpenMPDeclareMapperConstruct &) { + currStmt_ = std::nullopt; + } + private: std::optional currStmt_; // current statement we are processing std::multimap symbols_; // location to symbol diff --git a/flang/module/ieee_arithmetic.f90 b/flang/module/ieee_arithmetic.f90 index 0e8d5f1af01e7b2a206bcd55b4dcf3a687fd04f2..45016e84de7a3720fb9e526d95590e7082da8b03 100644 --- a/flang/module/ieee_arithmetic.f90 +++ b/flang/module/ieee_arithmetic.f90 @@ -161,6 +161,11 @@ module ieee_arithmetic ! Define specifics with 1 or 2 INTEGER, LOGICAL, or REAL arguments for ! generic G. +! +! The result type of most function specifics is either a fixed type or +! the type of the first argument. The result type of a SPECIFICS_rRR +! function call is the highest precision argument type. + #define SPECIFICS_I(G) \ G(1) G(2) G(4) G(8) G(16) #define SPECIFICS_L(G) \ @@ -234,6 +239,13 @@ module ieee_arithmetic G(8,2) G(8,3) G(8,4) G(8,8) G(8,10) G(8,16) \ G(10,2) G(10,3) G(10,4) G(10,8) G(10,10) G(10,16) \ G(16,2) G(16,3) G(16,4) G(16,8) G(16,10) G(16,16) +#define SPECIFICS_rRR(G) \ + G(2,2,2) G(2,2,3) G(4,2,4) G(8,2,8) G(10,2,10) G(16,2,16) \ + G(2,3,2) G(3,3,3) G(4,3,4) G(8,3,8) G(10,3,10) G(16,3,16) \ + G(4,4,2) G(4,4,3) G(4,4,4) G(8,4,8) G(10,4,10) G(16,4,16) \ + G(8,8,2) G(8,8,3) G(8,8,4) G(8,8,8) G(10,8,10) G(16,8,16) \ + G(10,10,2) G(10,10,3) G(10,10,4) G(10,10,8) G(10,10,10) G(16,10,16) \ + G(16,16,2) G(16,16,3) G(16,16,4) G(16,16,8) G(16,16,10) G(16,16,16) #else #define SPECIFICS_RR(G) \ G(2,2) G(2,3) G(2,4) G(2,8) G(2,16) \ @@ -241,6 +253,12 @@ module ieee_arithmetic G(4,2) G(4,3) G(4,4) G(4,8) G(4,16) \ G(8,2) G(8,3) G(8,4) G(8,8) G(8,16) \ G(16,2) G(16,3) G(16,4) G(16,8) G(16,16) +#define SPECIFICS_rRR(G) \ + G(2,2,2) G(2,2,3) G(4,2,4) G(8,2,8) G(16,2,16) \ + G(2,3,2) G(3,3,3) G(4,3,4) G(8,3,8) G(16,3,16) \ + G(4,4,2) G(4,4,3) G(4,4,4) G(8,4,8) G(16,4,16) \ + G(8,8,2) G(8,8,3) G(8,8,4) G(8,8,8) G(16,8,16) \ + G(16,16,2) G(16,16,3) G(16,16,4) G(16,16,8) G(16,16,16) #endif #else #if __x86_64__ @@ -250,12 +268,23 @@ module ieee_arithmetic G(4,2) G(4,3) G(4,4) G(4,8) G(4,10) \ G(8,2) G(8,3) G(8,4) G(8,8) G(8,10) \ G(10,2) G(10,3) G(10,4) G(10,8) G(10,10) +#define SPECIFICS_rRR(G) \ + G(2,2,2) G(2,2,3) G(4,2,4) G(8,2,8) G(10,2,10) \ + G(2,3,2) G(3,3,3) G(4,3,4) G(8,3,8) G(10,3,10) \ + G(4,4,2) G(4,4,3) G(4,4,4) G(8,4,8) G(10,4,10) \ + G(8,8,2) G(8,8,3) G(8,8,4) G(8,8,8) G(10,8,10) \ + G(10,10,2) G(10,10,3) G(10,10,4) G(10,10,8) G(10,10,10) #else #define SPECIFICS_RR(G) \ G(2,2) G(2,3) G(2,4) G(2,8) \ G(3,2) G(3,3) G(3,4) G(3,8) \ G(4,2) G(4,3) G(4,4) G(4,8) \ G(8,2) G(8,3) G(8,4) G(8,8) +#define SPECIFICS_rRR(G) \ + G(2,2,2) G(2,2,3) G(4,2,4) G(8,2,8) \ + G(2,3,2) G(3,3,3) G(4,3,4) G(8,3,8) \ + G(4,4,2) G(4,4,3) G(4,4,4) G(8,4,8) \ + G(8,8,2) G(8,8,3) G(8,8,4) G(8,8,8) #endif #endif @@ -467,16 +496,16 @@ module ieee_arithmetic public :: ieee_quiet_ne #undef IEEE_QUIET_NE_R -#define IEEE_REM_RR(XKIND, YKIND) \ - elemental real(XKIND) function ieee_rem_a##XKIND##_a##YKIND(x, y); \ +#define IEEE_REM_rRR(RKIND, XKIND, YKIND) \ + elemental real(RKIND) function ieee_rem_a##XKIND##_a##YKIND(x, y); \ real(XKIND), intent(in) :: x; \ real(YKIND), intent(in) :: y; \ end function ieee_rem_a##XKIND##_a##YKIND; interface ieee_rem - SPECIFICS_RR(IEEE_REM_RR) + SPECIFICS_rRR(IEEE_REM_rRR) end interface ieee_rem public :: ieee_rem -#undef IEEE_REM_RR +#undef IEEE_REM_rRR #define IEEE_RINT_R(XKIND) \ elemental real(XKIND) function ieee_rint_a##XKIND(x, round); \ diff --git a/flang/runtime/CUDA/memory.cpp b/flang/runtime/CUDA/memory.cpp index 7b40b837e7666e8629a9230d6503ed8c07af0ab6..68963c4d7738acd9e3b4194e1724ab42dda8b590 100644 --- a/flang/runtime/CUDA/memory.cpp +++ b/flang/runtime/CUDA/memory.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Runtime/CUDA/memory.h" +#include "../assign-impl.h" #include "../terminator.h" #include "flang/Runtime/CUDA/common.h" #include "flang/Runtime/CUDA/descriptor.h" @@ -120,6 +121,24 @@ void RTDECL(CUFDataTransferDescDesc)(Descriptor *dstDesc, Descriptor *srcDesc, *dstDesc, *srcDesc, terminator, MaybeReallocate, memmoveFct); } +void RTDECL(CUFDataTransferCstDesc)(Descriptor *dstDesc, Descriptor *srcDesc, + unsigned mode, const char *sourceFile, int sourceLine) { + MemmoveFct memmoveFct; + Terminator terminator{sourceFile, sourceLine}; + if (mode == kHostToDevice) { + memmoveFct = &MemmoveHostToDevice; + } else if (mode == kDeviceToHost) { + memmoveFct = &MemmoveDeviceToHost; + } else if (mode == kDeviceToDevice) { + memmoveFct = &MemmoveDeviceToDevice; + } else { + terminator.Crash("host to host copy not supported"); + } + + Fortran::runtime::DoFromSourceAssign( + *dstDesc, *srcDesc, terminator, memmoveFct); +} + void RTDECL(CUFDataTransferDescDescNoRealloc)(Descriptor *dstDesc, Descriptor *srcDesc, unsigned mode, const char *sourceFile, int sourceLine) { diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt index c8a51cc2508b9f62e25ce5634ffc3b18554a8699..703f85fcaf8dacb9c61ed3ab2be9730cec4cc0cd 100644 --- a/flang/runtime/Float128Math/CMakeLists.txt +++ b/flang/runtime/Float128Math/CMakeLists.txt @@ -51,6 +51,7 @@ set(sources norm2.cpp pow.cpp random.cpp + remainder.cpp round.cpp rrspacing.cpp scale.cpp diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h index 4600c726d72825520972851c8a3451b895f15565..a94503fe8e67a09ed8a465435744e863b1fdb3c2 100644 --- a/flang/runtime/Float128Math/math-entries.h +++ b/flang/runtime/Float128Math/math-entries.h @@ -96,6 +96,7 @@ DEFINE_FALLBACK_F128(Nearbyint) DEFINE_FALLBACK_F128(Nextafter) DEFINE_FALLBACK_F128(Pow) DEFINE_FALLBACK_F128(Qnan) +DEFINE_FALLBACK_F128(Remainder) DEFINE_FALLBACK_F128(Round) DEFINE_FALLBACK_F128(Sin) DEFINE_FALLBACK_F128(Sinh) @@ -144,6 +145,7 @@ DEFINE_SIMPLE_ALIAS(Lround, lroundq) DEFINE_SIMPLE_ALIAS(Nearbyint, nearbyintq) DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq) DEFINE_SIMPLE_ALIAS(Pow, powq) +DEFINE_SIMPLE_ALIAS(Remainder, remainderq) DEFINE_SIMPLE_ALIAS(Round, roundq) DEFINE_SIMPLE_ALIAS(Sin, sinq) DEFINE_SIMPLE_ALIAS(Sinh, sinhq) @@ -196,6 +198,7 @@ DEFINE_SIMPLE_ALIAS(Lround, std::lround) DEFINE_SIMPLE_ALIAS(Nearbyint, std::nearbyint) DEFINE_SIMPLE_ALIAS(Nextafter, std::nextafter) DEFINE_SIMPLE_ALIAS(Pow, std::pow) +DEFINE_SIMPLE_ALIAS(Remainder, std::remainder) DEFINE_SIMPLE_ALIAS(Round, std::round) DEFINE_SIMPLE_ALIAS(Sin, std::sin) DEFINE_SIMPLE_ALIAS(Sinh, std::sinh) diff --git a/flang/runtime/Float128Math/remainder.cpp b/flang/runtime/Float128Math/remainder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5c2793dab71aff148e1a8778c76a659d967843c --- /dev/null +++ b/flang/runtime/Float128Math/remainder.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/remainder.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 "math-entries.h" + +namespace Fortran::runtime { +extern "C" { + +#if HAS_LDBL128 || HAS_FLOAT128 +CppTypeFor RTDEF(RemainderF128)( + CppTypeFor x, + CppTypeFor y) { + return Remainder::invoke(x, y); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/assign-impl.h b/flang/runtime/assign-impl.h index f07a501d1d126325b00d9d87ae69c6ac4c4dde42..aaa320ef7f9591633ad52002a677a97f0f4bb659 100644 --- a/flang/runtime/assign-impl.h +++ b/flang/runtime/assign-impl.h @@ -9,6 +9,8 @@ #ifndef FORTRAN_RUNTIME_ASSIGN_IMPL_H_ #define FORTRAN_RUNTIME_ASSIGN_IMPL_H_ +#include "flang/Runtime/freestanding-tools.h" + namespace Fortran::runtime { class Descriptor; class Terminator; @@ -17,8 +19,13 @@ class Terminator; // Note that if allocate object and source expression have the same rank, the // value of the allocate object becomes the value provided; otherwise the value // of each element of allocate object becomes the value provided (9.7.1.2(7)). -RT_API_ATTRS void DoFromSourceAssign( - Descriptor &, const Descriptor &, Terminator &); +#ifdef RT_DEVICE_COMPILATION +RT_API_ATTRS void DoFromSourceAssign(Descriptor &, const Descriptor &, + Terminator &, MemmoveFct memmoveFct = &MemmoveWrapper); +#else +RT_API_ATTRS void DoFromSourceAssign(Descriptor &, const Descriptor &, + Terminator &, MemmoveFct memmoveFct = &Fortran::runtime::memmove); +#endif } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_ASSIGN_IMPL_H_ diff --git a/flang/runtime/assign.cpp b/flang/runtime/assign.cpp index 83c0b9c70ed0d15161d2beb796ac727a60274414..8f0efaa376c1984efd81f561ffb6607e9b0a88a5 100644 --- a/flang/runtime/assign.cpp +++ b/flang/runtime/assign.cpp @@ -509,8 +509,8 @@ RT_API_ATTRS void Assign(Descriptor &to, const Descriptor &from, RT_OFFLOAD_API_GROUP_BEGIN -RT_API_ATTRS void DoFromSourceAssign( - Descriptor &alloc, const Descriptor &source, Terminator &terminator) { +RT_API_ATTRS void DoFromSourceAssign(Descriptor &alloc, + const Descriptor &source, Terminator &terminator, MemmoveFct memmoveFct) { if (alloc.rank() > 0 && source.rank() == 0) { // The value of each element of allocate object becomes the value of source. DescriptorAddendum *allocAddendum{alloc.Addendum()}; @@ -523,17 +523,17 @@ RT_API_ATTRS void DoFromSourceAssign( alloc.IncrementSubscripts(allocAt)) { Descriptor allocElement{*Descriptor::Create(*allocDerived, reinterpret_cast(alloc.Element(allocAt)), 0)}; - Assign(allocElement, source, terminator, NoAssignFlags); + Assign(allocElement, source, terminator, NoAssignFlags, memmoveFct); } } else { // intrinsic type for (std::size_t n{alloc.Elements()}; n-- > 0; alloc.IncrementSubscripts(allocAt)) { - Fortran::runtime::memmove(alloc.Element(allocAt), - source.raw().base_addr, alloc.ElementBytes()); + memmoveFct(alloc.Element(allocAt), source.raw().base_addr, + alloc.ElementBytes()); } } } else { - Assign(alloc, source, terminator, NoAssignFlags); + Assign(alloc, source, terminator, NoAssignFlags, memmoveFct); } } diff --git a/flang/runtime/transformational.cpp b/flang/runtime/transformational.cpp index b65502933b862fd4c58918e7b06805ddc7b5634e..ab303bdef9b1d145e95b5c7d70811028cf809110 100644 --- a/flang/runtime/transformational.cpp +++ b/flang/runtime/transformational.cpp @@ -46,7 +46,7 @@ public: lb_[k++] = shiftDim.LowerBound(); if (shiftDim.Extent() != source.GetDimension(j).Extent()) { terminator_.Crash("%s: on dimension %d, SHIFT= has extent %jd but " - "SOURCE= has extent %jd", + "ARRAY= has extent %jd", which, k, static_cast(shiftDim.Extent()), static_cast(source.GetDimension(j).Extent())); } @@ -460,7 +460,7 @@ void RTDEF(Cshift)(Descriptor &result, const Descriptor &source, RUNTIME_CHECK(terminator, rank > 1); if (dim < 1 || dim > rank) { terminator.Crash( - "CSHIFT: DIM=%d must be >= 1 and <= SOURCE= rank %d", dim, rank); + "CSHIFT: DIM=%d must be >= 1 and <= ARRAY= rank %d", dim, rank); } ShiftControl shiftControl{shift, terminator, dim}; shiftControl.Init(source, "CSHIFT"); @@ -527,7 +527,7 @@ void RTDEF(Eoshift)(Descriptor &result, const Descriptor &source, RUNTIME_CHECK(terminator, rank > 1); if (dim < 1 || dim > rank) { terminator.Crash( - "EOSHIFT: DIM=%d must be >= 1 and <= SOURCE= rank %d", dim, rank); + "EOSHIFT: DIM=%d must be >= 1 and <= ARRAY= rank %d", dim, rank); } std::size_t elementLen{ AllocateResult(result, source, rank, extent, terminator, "EOSHIFT")}; @@ -538,7 +538,7 @@ void RTDEF(Eoshift)(Descriptor &result, const Descriptor &source, RUNTIME_CHECK(terminator, boundary->type() == source.type()); if (boundary->ElementBytes() != elementLen) { terminator.Crash("EOSHIFT: BOUNDARY= has element byte length %zd, but " - "SOURCE= has length %zd", + "ARRAY= has length %zd", boundary->ElementBytes(), elementLen); } if (boundaryRank > 0) { @@ -547,7 +547,7 @@ void RTDEF(Eoshift)(Descriptor &result, const Descriptor &source, if (j != dim - 1) { if (boundary->GetDimension(k).Extent() != extent[j]) { terminator.Crash("EOSHIFT: BOUNDARY= has extent %jd on dimension " - "%d but must conform with extent %jd of SOURCE=", + "%d but must conform with extent %jd of ARRAY=", static_cast(boundary->GetDimension(k).Extent()), k + 1, static_cast(extent[j])); } @@ -611,7 +611,7 @@ void RTDEF(EoshiftVector)(Descriptor &result, const Descriptor &source, RUNTIME_CHECK(terminator, boundary->type() == source.type()); if (boundary->ElementBytes() != elementLen) { terminator.Crash("EOSHIFT: BOUNDARY= has element byte length %zd but " - "SOURCE= has length %zd", + "ARRAY= has length %zd", boundary->ElementBytes(), elementLen); } } @@ -658,7 +658,7 @@ void RTDEF(Pack)(Descriptor &result, const Descriptor &source, RUNTIME_CHECK(terminator, vector->rank() == 1); RUNTIME_CHECK(terminator, source.type() == vector->type()); if (source.ElementBytes() != vector->ElementBytes()) { - terminator.Crash("PACK: SOURCE= has element byte length %zd, but VECTOR= " + terminator.Crash("PACK: ARRAY= has element byte length %zd, but VECTOR= " "has length %zd", source.ElementBytes(), vector->ElementBytes()); } diff --git a/flang/test/Driver/dynamic-linker.f90 b/flang/test/Driver/dynamic-linker.f90 index 6d5c443ab75cb3c9ca5e4b9c3be0c87a3eb65d68..e850939374568c772a4287e10fe2a3a86e668fe6 100644 --- a/flang/test/Driver/dynamic-linker.f90 +++ b/flang/test/Driver/dynamic-linker.f90 @@ -17,7 +17,7 @@ ! GNU-LINKER-OPTIONS-SAME: "-static" ! GNU-LINKER-OPTIONS-SAME: "-rpath" "/path/to/dir" -! RDYNAMIC-LINKER-OPTION: "{{.*}}ld" +! RDYNAMIC-LINKER-OPTION: "{{.*}}ld{{(\.lld)?(\.exe)?}}" ! RDYNAMIC-LINKER-OPTION-SAME: "-export-dynamic" ! For MSVC, adding -static does not add any additional linker options. diff --git a/flang/test/Driver/isysroot.f90 b/flang/test/Driver/isysroot.f90 index 28b435cce08edd3e4da7b2e87b3778bc43ac20a1..07ffb686531471cfc2fbbd50db6bdce95af20565 100644 --- a/flang/test/Driver/isysroot.f90 +++ b/flang/test/Driver/isysroot.f90 @@ -8,7 +8,7 @@ ! RUN: %flang -### --target=aarch64-linux-gnu -isysroot /path/to/sysroot \ ! RUN: %s 2>&1 | FileCheck %s --check-prefix=CHECK-LINUX -! CHECK-DARWIN: "{{.*}}ld{{(64)?(\.lld)?}}" {{.*}}"-syslibroot" "/path/to/sysroot" +! CHECK-DARWIN: "{{.*}}ld{{(64)?(\.lld)?(\.exe)?}}" {{.*}}"-syslibroot" "/path/to/sysroot" ! Unused on Linux. ! CHECK-LINUX: warning: argument unused during compilation: '-isysroot /path/to/sysroot' ! CHECK-LINUX-NOT: /path/to/sysroot diff --git a/flang/test/Driver/target-cpu-features.f90 b/flang/test/Driver/target-cpu-features.f90 index e3eb8491058c7f8ce7eadf5ca6e0ec92c0e81791..5a3fd0d8380027c568a4c01a37e8f6568eb634e0 100644 --- a/flang/test/Driver/target-cpu-features.f90 +++ b/flang/test/Driver/target-cpu-features.f90 @@ -41,6 +41,9 @@ ! RUN: %flang --target=r600-unknown-unknown -mcpu=cayman -nogpulib -c %s -### 2>&1 \ ! RUN: | FileCheck %s -check-prefix=CHECK-AMDGPU-R600 +! RUN: %flang --target=loongarch64-linux-gnu -c %s -### 2>&1 \ +! RUN: | FileCheck %s -check-prefix=CHECK-LOONGARCH64 + ! 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 @@ -86,3 +89,6 @@ ! CHECK-AMDGPU-R600: "-fc1" "-triple" "r600-unknown-unknown" ! CHECK-AMDGPU-R600-SAME: "-target-cpu" "cayman" + +! 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" diff --git a/flang/test/Evaluate/bug115923.f90 b/flang/test/Evaluate/bug115923.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ccddab02f5a11b294da30fc997a01be9a9d45f1d --- /dev/null +++ b/flang/test/Evaluate/bug115923.f90 @@ -0,0 +1,22 @@ +! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s +! Ensure that EOSHIFT's ARRAY= argument and result can be CLASS(*). +! CHECK-NOT: error: +! CHECK: warning: Source of TRANSFER is polymorphic +! CHECK: warning: Mold of TRANSFER is polymorphic +program p + type base + integer j + end type + type, extends(base) :: extended + integer k + end type + class(base), allocatable :: polyArray(:,:,:) + class(*), allocatable :: unlimited(:) + allocate(polyArray, source=reshape([(extended(n,n-1),n=1,8)],[2,2,2])) + allocate(unlimited, source=[(base(9),n=1,16)]) + select type (x => eoshift(transfer(polyArray, unlimited), -4, base(-1))) + type is (base); print *, 'base', x + type is (extended); print *, 'extended?', x + class default; print *, 'class default??' + end select +end diff --git a/flang/test/Evaluate/folding09.f90 b/flang/test/Evaluate/folding09.f90 index 863b5e873a1e5b0f71bc736101b96c94a4209674..534ff1a89a174d7f439dfd6ef810e9fd4a7608d6 100644 --- a/flang/test/Evaluate/folding09.f90 +++ b/flang/test/Evaluate/folding09.f90 @@ -5,7 +5,7 @@ module m real, target :: hosted(2) integer, parameter :: cst(2,2) = reshape([1, 2, 3, 4], shape(cst)) integer, parameter :: empty_cst(2,0) = reshape([1], shape(empty_cst)) - integer :: n + integer :: n, m logical, parameter :: test_param1 = is_contiguous(cst(:,1)) logical, parameter :: test_param2 = is_contiguous(cst(1,:)) logical, parameter :: test_param3 = is_contiguous(cst(:,n)) @@ -16,11 +16,15 @@ module m real, pointer, contiguous :: f(:) f => hosted end function - subroutine test(arr1, arr2, arr3, mat, alloc) + subroutine test(arr1, arr2, arr3, mat, alloc, alch) real, intent(in) :: arr1(:), arr2(10), mat(10, 10) real, intent(in), contiguous :: arr3(:) real, allocatable :: alloc(:) real :: scalar + character(5) charr(5) + character(1) char1(5) + character(0) char0(5) + character(*) alch(5) integer(kind=merge(1,-1, is_contiguous(0))) t01 integer(kind=merge(1,-1, is_contiguous(scalar))) t02 integer(kind=merge(1,-1, is_contiguous(scalar + scalar))) t03 @@ -35,6 +39,17 @@ module m integer(kind=merge(1,-1, .not. is_contiguous(arr3(1:10:2)))) t12 integer(kind=merge(1,-1, is_contiguous(f()))) t13 integer(kind=merge(1,-1, is_contiguous(alloc))) t14 + integer(kind=merge(1,-1, is_contiguous(charr(:)(:)))) t15 + integer(kind=merge(1,-1, is_contiguous(charr(1)(2:3)))) t16 + integer(kind=merge(1,-1, is_contiguous(charr(:)(1:)))) t17 + integer(kind=merge(1,-1, is_contiguous(charr(:)(3:2)))) t18 + integer(kind=merge(1,-1, is_contiguous(charr(:)(1:5)))) t19 + integer(kind=merge(1,-1, .not. is_contiguous(charr(:)(1:4)))) t20 + integer(kind=merge(1,-1, is_contiguous(char1(:)(n:m)))) t21 + integer(kind=merge(1,-1, .not. is_contiguous(char1(1:5:2)(n:m)))) t22 + integer(kind=merge(1,-1, is_contiguous(char0(:)(n:m)))) t23 + integer(kind=merge(1,-1, is_contiguous(char0(1:5:2)(n:m)))) t24 + integer(kind=merge(1,-1, is_contiguous(alch(:)(:)))) t25 associate (x => arr2) block integer(kind=merge(1,-1,is_contiguous(x))) n diff --git a/flang/test/Evaluate/int8.f90 b/flang/test/Evaluate/int8.f90 index ef8321f4c710b38161c1ee4d3de876399f52857d..677f1b15a076a4ed91d8e07b3b024cb7714904a9 100644 --- a/flang/test/Evaluate/int8.f90 +++ b/flang/test/Evaluate/int8.f90 @@ -1,5 +1,7 @@ -! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +!RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s !CHECK: warning: REAL(4) to INTEGER(2) conversion overflowed -!CHECK: PRINT *, 32767_2, 4000000000_8 print *, int2(4.e9), int8(4.e9) +!CHECK: error: 'int2' is not an unrestricted specific intrinsic procedure +!CHECK: error: 'int8' is not an unrestricted specific intrinsic procedure +call foo(int2,int8) end diff --git a/flang/test/Fir/CUDA/cuda-alloc-free.fir b/flang/test/Fir/CUDA/cuda-alloc-free.fir index 88b1a00e4a5b25c6ae651093568a723b677c7e07..abf2d56695b1728c6532c1f1f15f470b7b98b177 100644 --- a/flang/test/Fir/CUDA/cuda-alloc-free.fir +++ b/flang/test/Fir/CUDA/cuda-alloc-free.fir @@ -73,4 +73,25 @@ func.func @_QPtest_type() { // CHECK: %[[CONV_BYTES:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: fir.call @_FortranACUFMemAlloc(%[[CONV_BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr +gpu.module @cuda_device_mod { + gpu.func @_QMalloc() kernel { + %0 = cuf.alloc !fir.box>> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QMallocEa"} -> !fir.ref>>> + gpu.return + } +} + +// CHECK-LABEL: gpu.func @_QMalloc() kernel +// CHECK: fir.alloca !fir.box>> {bindc_name = "a", uniq_name = "_QMallocEa"} + +func.func @_QQalloc_char() attributes {fir.bindc_name = "alloc_char"} { + %c1 = arith.constant 1 : index + %0 = cuf.alloc !fir.array<10x!fir.char<1>>(%c1 : index) {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFEa"} -> !fir.ref>> + return +} + +// CHECK-LABEL: func.func @_QQalloc_char() +// CHECK: %[[BYTES:.*]] = arith.muli %c10{{.*}}, %c1{{.*}} : index +// CHECK: %[[BYTES_CONV:.*]] = fir.convert %[[BYTES]] : (index) -> i64 +// CHECK: fir.call @_FortranACUFMemAlloc(%[[BYTES_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr + } // end module diff --git a/flang/test/Fir/CUDA/cuda-constructor-2.f90 b/flang/test/Fir/CUDA/cuda-constructor-2.f90 index 99386abc4fafdd0998f48ca9bc136511bb3ab145..901497e2cde55079e141c9b139ce1167386373ee 100644 --- a/flang/test/Fir/CUDA/cuda-constructor-2.f90 +++ b/flang/test/Fir/CUDA/cuda-constructor-2.f90 @@ -10,11 +10,11 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry>> } - gpu.module @cuda_device_mod [#nvvm.target] { + gpu.module @cuda_device_mod { } } -// CHECK: gpu.module @cuda_device_mod [#nvvm.target] +// CHECK: gpu.module @cuda_device_mod // CHECK: llvm.func internal @__cudaFortranConstructor() { // CHECK-DAG: %[[MODULE:.*]] = cuf.register_module @cuda_device_mod -> !llvm.ptr diff --git a/flang/test/Fir/CUDA/cuda-data-transfer.fir b/flang/test/Fir/CUDA/cuda-data-transfer.fir index 8497aee2e2cf9c2052eaf03bab2109eebbd859a9..0f9ca6e640a802471d47b6ea9271f845a0e5e2da 100644 --- a/flang/test/Fir/CUDA/cuda-data-transfer.fir +++ b/flang/test/Fir/CUDA/cuda-data-transfer.fir @@ -38,7 +38,7 @@ func.func @_QPsub2() { // CHECK: fir.store %[[EMBOX]] to %[[TEMP_BOX]] : !fir.ref> // CHECK: %[[ADEV_BOX:.*]] = fir.convert %[[ADEV]]#0 : (!fir.ref>>>) -> !fir.ref> // CHECK: %[[TEMP_CONV:.*]] = fir.convert %[[TEMP_BOX]] : (!fir.ref>) -> !fir.ref> -// CHECK: fir.call @_FortranACUFDataTransferDescDesc(%[[ADEV_BOX]], %[[TEMP_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none +// CHECK: fir.call @_FortranACUFDataTransferCstDesc(%[[ADEV_BOX]], %[[TEMP_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none func.func @_QPsub3() { %0 = cuf.alloc !fir.box>> {bindc_name = "adev", data_attr = #cuf.cuda, uniq_name = "_QFsub3Eadev"} -> !fir.ref>>> @@ -58,7 +58,7 @@ func.func @_QPsub3() { // CHECK: fir.store %[[EMBOX]] to %[[TEMP_BOX]] : !fir.ref> // CHECK: %[[ADEV_BOX:.*]] = fir.convert %[[ADEV]]#0 : (!fir.ref>>>) -> !fir.ref> // CHECK: %[[V_CONV:.*]] = fir.convert %[[TEMP_BOX]] : (!fir.ref>) -> !fir.ref> -// CHECK: fir.call @_FortranACUFDataTransferDescDesc(%[[ADEV_BOX]], %[[V_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none +// CHECK: fir.call @_FortranACUFDataTransferCstDesc(%[[ADEV_BOX]], %[[V_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none func.func @_QPsub4() { %0 = cuf.alloc !fir.box>> {bindc_name = "adev", data_attr = #cuf.cuda, uniq_name = "_QFsub4Eadev"} -> !fir.ref>>> @@ -202,7 +202,9 @@ func.func @_QPsub8() attributes {fir.bindc_name = "t"} { // CHECK: %[[DECL:.*]] = fir.declare %[[GBL]] // CHECK: %[[HOST:.*]] = fir.convert %[[DECL]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: %[[SRC:.*]] = fir.call @_FortranACUFGetDeviceAddress(%[[HOST]], %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr +// CHECK: %[[SRC_CONV:.*]] = fir.convert %[[SRC]] : (!fir.llvm_ptr) -> !fir.ref> // CHECK: %[[DST:.*]] = fir.convert %[[LOCAL]] : (!fir.ref>) -> !fir.llvm_ptr +// CHECK: %[[SRC:.*]] = fir.convert %[[SRC_CONV]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[DST]], %[[SRC]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none @@ -224,6 +226,8 @@ func.func @_QPsub9() { // CHECK: %[[DECL:.*]] = fir.declare %[[GBL]] // CHECK: %[[HOST:.*]] = fir.convert %[[DECL]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: %[[DST:.*]] = fir.call @_FortranACUFGetDeviceAddress(%[[HOST]], %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr +// CHECK: %[[DST_CONV:.*]] = fir.convert %[[DST]] : (!fir.llvm_ptr) -> !fir.ref> +// CHECK: %[[DST:.*]] = fir.convert %[[DST_CONV]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: %[[SRC:.*]] = fir.convert %[[LOCAL]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[DST]], %[[SRC]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none @@ -293,6 +297,260 @@ func.func @_QPscalar_to_array() { } // CHECK-LABEL: func.func @_QPscalar_to_array() -// CHECK: _FortranACUFDataTransferDescDescNoRealloc +// CHECK: _FortranACUFDataTransferCstDesc + +func.func @_QPtest_type() { + %0 = cuf.alloc !fir.type<_QMbarTcmplx{id:i32,c:complex}> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFtest_typeEa"} -> !fir.ref}>> + %1 = fir.declare %0 {data_attr = #cuf.cuda, uniq_name = "_QFtest_typeEa"} : (!fir.ref}>>) -> !fir.ref}>> + %2 = fir.alloca !fir.type<_QMbarTcmplx{id:i32,c:complex}> {bindc_name = "b", uniq_name = "_QFtest_typeEb"} + %3 = fir.declare %2 {uniq_name = "_QFtest_typeEb"} : (!fir.ref}>>) -> !fir.ref}>> + cuf.data_transfer %3 to %1 {transfer_kind = #cuf.cuda_transfer} : !fir.ref}>>, !fir.ref}>> + cuf.free %1 : !fir.ref}>> {data_attr = #cuf.cuda} + return +} + +// CHECK-LABEL: func.func @_QPtest_type() +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%{{.*}}, %{{.*}}, %c12{{.*}}, %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none + +func.func @_QPtest_array_type() { + %c10 = arith.constant 10 : index + %0 = cuf.alloc !fir.array<10x!fir.type<_QMbarTcmplx{id:i32,c:complex}>> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFtest_array_typeEa"} -> !fir.ref}>>> + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2 = fir.declare %0(%1) {data_attr = #cuf.cuda, uniq_name = "_QFtest_array_typeEa"} : (!fir.ref}>>>, !fir.shape<1>) -> !fir.ref}>>> + %3 = fir.alloca !fir.array<10x!fir.type<_QMbarTcmplx{id:i32,c:complex}>> {bindc_name = "b", uniq_name = "_QFtest_array_typeEb"} + %4 = fir.declare %3(%1) {uniq_name = "_QFtest_array_typeEb"} : (!fir.ref}>>>, !fir.shape<1>) -> !fir.ref}>>> + cuf.data_transfer %4 to %2 {transfer_kind = #cuf.cuda_transfer} : !fir.ref}>>>, !fir.ref}>>> + cuf.free %2 : !fir.ref}>>> {data_attr = #cuf.cuda} + return +} + +// CHECK-LABEL: func.func @_QPtest_array_type() +// CHECK: %[[BYTES:.*]] = arith.muli %c10{{.*}}, %c12 : index +// CHECK: %[[CONV_BYTES:.*]] = fir.convert %[[BYTES]] : (index) -> i64 +// CHECK: fir.call @_FortranACUFMemAlloc(%[[CONV_BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr +// CHECK: %[[BYTES:.*]] = arith.muli %c10{{.*}}, %c12{{.*}} : i64 +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%{{.*}}, %{{.*}}, %[[BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none + +func.func @_QPshape_shift() { + %c0_i32 = arith.constant 0 : i32 + %c11 = arith.constant 11 : index + %c10 = arith.constant 10 : index + %0 = cuf.alloc !fir.array<10xi32> {bindc_name = "cdev", data_attr = #cuf.cuda, uniq_name = "_QFshape_shiftEcdev"} -> !fir.ref> + %1 = fir.shape_shift %c11, %c10 : (index, index) -> !fir.shapeshift<1> + %2:2 = hlfir.declare %0(%1) {data_attr = #cuf.cuda, uniq_name = "_QFshape_shiftEcdev"} : (!fir.ref>, !fir.shapeshift<1>) -> (!fir.box>, !fir.ref>) + cuf.data_transfer %c0_i32 to %2#1, %1 : !fir.shapeshift<1> {transfer_kind = #cuf.cuda_transfer} : i32, !fir.ref> + cuf.free %2#1 : !fir.ref> {data_attr = #cuf.cuda} + return +} + +// CHECK-LABEL: func.func @_QPshape_shift() +// CHECK: fir.call @_FortranACUFDataTransferCstDesc + +func.func @_QPshape_shift2() { + %c11 = arith.constant 11 : index + %c10 = arith.constant 10 : index + %0 = fir.alloca !fir.array<10xi32> {bindc_name = "ahost", uniq_name = "_QFshape_shift2Eahost"} + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2:2 = hlfir.declare %0(%1) {uniq_name = "_QFshape_shift2Eahost"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %3 = cuf.alloc !fir.array<10xi32> {bindc_name = "cdev", data_attr = #cuf.cuda, uniq_name = "_QFshape_shift2Ecdev"} -> !fir.ref> + %4 = fir.shape_shift %c11, %c10 : (index, index) -> !fir.shapeshift<1> + %5:2 = hlfir.declare %3(%4) {data_attr = #cuf.cuda, uniq_name = "_QFshape_shift2Ecdev"} : (!fir.ref>, !fir.shapeshift<1>) -> (!fir.box>, !fir.ref>) + cuf.data_transfer %2#0 to %5#1, %4 : !fir.shapeshift<1> {transfer_kind = #cuf.cuda_transfer} : !fir.ref>, !fir.ref> + cuf.free %5#1 : !fir.ref> {data_attr = #cuf.cuda} + return +} + +// CHECK-LABEL: func.func @_QPshape_shift2() +// CHECK: %[[C10:.*]] = fir.convert %c10{{.*}} : (index) -> i64 +// CHECK: %[[BYTES:.*]] = arith.muli %[[C10]], %c4{{.*}} : i64 +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%{{.*}}, %{{.*}}, %[[BYTES]], %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none + +fir.global @_QMmod1Ea_dev {data_attr = #cuf.cuda} : !fir.array<4xf32> { + %0 = fir.zero_bits !fir.array<4xf32> + fir.has_value %0 : !fir.array<4xf32> +} +func.func @_QPdevice_addr_conv() { + %cst = arith.constant 4.200000e+01 : f32 + %c4 = arith.constant 4 : index + %0 = fir.address_of(@_QMmod1Ea_dev) : !fir.ref> + %1 = fir.shape %c4 : (index) -> !fir.shape<1> + %2 = fir.declare %0(%1) {data_attr = #cuf.cuda, uniq_name = "_QMmod1Ea_dev"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> + cuf.data_transfer %cst to %2 {transfer_kind = #cuf.cuda_transfer} : f32, !fir.ref> + return +} + +// CHECK-LABEL: func.func @_QPdevice_addr_conv() +// CHECK: %[[DEV_ADDR:.*]] = fir.call @_FortranACUFGetDeviceAddress(%{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr +// CHECK: %[[DEV_ADDR_CONV:.*]] = fir.convert %[[DEV_ADDR]] : (!fir.llvm_ptr) -> !fir.ref> +// CHECK: fir.embox %[[DEV_ADDR_CONV]](%{{.*}}) : (!fir.ref>, !fir.shape<1>) -> !fir.box> +// CHECK: fir.call @_FortranACUFDataTransferCstDesc + +func.func @_QQchar_transfer() attributes {fir.bindc_name = "char_transfer"} { + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + %0 = cuf.alloc !fir.array<10x!fir.char<1>>(%c1 : index) {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFEa"} -> !fir.ref>> + %1 = fir.shape %c10 : (index) -> !fir.shape<1> + %2 = fir.declare %0(%1) typeparams %c1 {data_attr = #cuf.cuda, uniq_name = "_QFEa"} : (!fir.ref>>, !fir.shape<1>, index) -> !fir.ref>> + %3 = fir.alloca !fir.array<10x!fir.char<1>> {bindc_name = "b", uniq_name = "_QFEb"} + %4 = fir.declare %3(%1) typeparams %c1 {uniq_name = "_QFEb"} : (!fir.ref>>, !fir.shape<1>, index) -> !fir.ref>> + cuf.data_transfer %4 to %2 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>>, !fir.ref>> + cuf.free %2 : !fir.ref>> {data_attr = #cuf.cuda} + return +} + +// CHECK-LABEL: func.func @_QQchar_transfer() +// CHECK: fir.call @_FortranACUFMemAlloc +// CHECK: %[[BYTES:.*]] = arith.muli %c10{{.*}}, %c1{{.*}} : i64 +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%{{.*}}, %{{.*}}, %[[BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none + +func.func @_QPdevmul(%arg0: !fir.ref> {fir.bindc_name = "b"}, %arg1: !fir.ref {fir.bindc_name = "wa"}, %arg2: !fir.ref {fir.bindc_name = "wb"}) { + %c0_i64 = arith.constant 0 : i64 + %c1_i32 = arith.constant 1 : i32 + %c0_i32 = arith.constant 0 : i32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFdevmulEwb"} : (!fir.ref, !fir.dscope) -> !fir.ref + %2 = cuf.alloc !fir.box>> {bindc_name = "bdev", data_attr = #cuf.cuda, uniq_name = "_QFdevmulEbdev"} -> !fir.ref>>> + %6 = fir.declare %2 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFdevmulEbdev"} : (!fir.ref>>>) -> !fir.ref>>> + %7 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFdevmulEwa"} : (!fir.ref, !fir.dscope) -> !fir.ref + %8 = fir.load %1 : !fir.ref + %9 = fir.convert %8 : (i32) -> index + %12 = fir.shape %c1, %9 : (index, index) -> !fir.shape<2> + %13 = fir.declare %arg0(%12) dummy_scope %0 {uniq_name = "_QFdevmulEb"} : (!fir.ref>, !fir.shape<2>, !fir.dscope) -> !fir.ref> + %24 = fir.load %7 : !fir.ref + %25 = fir.convert %24 : (i32) -> index + %26 = arith.cmpi sgt, %25, %c0 : index + %27 = arith.select %26, %25, %c0 : index + %28 = fir.load %1 : !fir.ref + %29 = fir.convert %28 : (i32) -> index + %30 = arith.cmpi sgt, %29, %c0 : index + %31 = arith.select %30, %29, %c0 : index + %32 = fir.shape %27, %31 : (index, index) -> !fir.shape<2> + %33 = fir.undefined index + %34 = fir.slice %c1, %25, %c1, %c1, %29, %c1 : (index, index, index, index, index, index) -> !fir.slice<2> + %35 = fir.embox %13(%12) [%34] : (!fir.ref>, !fir.shape<2>, !fir.slice<2>) -> !fir.box> + cuf.data_transfer %35 to %6 {transfer_kind = #cuf.cuda_transfer} : !fir.box>, !fir.ref>>> + cuf.data_transfer %6 to %35 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>>>, !fir.box> + return +} + +// CHECK-LABEL: func.func @_QPdevmul(%arg0: !fir.ref> {fir.bindc_name = "b"}, %arg1: !fir.ref {fir.bindc_name = "wa"}, %arg2: !fir.ref {fir.bindc_name = "wb"}) { +// CHECK: %[[ALLOCA0:.*]] = fir.alloca !fir.box> +// CHECK: %[[ALLOCA1:.*]] = fir.alloca !fir.box> +// CHECK: %[[EMBOX:.*]] = fir.embox %{{.*}}(%{{.*}}) [%{{.*}}] : (!fir.ref>, !fir.shape<2>, !fir.slice<2>) -> !fir.box> +// CHECK: fir.store %[[EMBOX]] to %[[ALLOCA1]] : !fir.ref>> +// CHECK: %[[SRC:.*]] = fir.convert %[[ALLOCA1]] : (!fir.ref>>) -> !fir.ref> +// CHECK: fir.call @_FortranACUFDataTransferDescDesc(%{{.*}}, %[[SRC]], %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none +// CHECK: fir.store %[[EMBOX]] to %[[ALLOCA0]] : !fir.ref>> +// CHECK: %[[DST:.*]] = fir.convert %[[ALLOCA0]] : (!fir.ref>>) -> !fir.ref> +// CHECK: fir.call @_FortranACUFDataTransferDescDesc(%[[DST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none + +func.func @_QPlogical_cst() { + %c0_i64 = arith.constant 0 : i64 + %false = arith.constant false + %c0 = arith.constant 0 : index + %0 = cuf.alloc !fir.box>>> {bindc_name = "id2", data_attr = #cuf.cuda, uniq_name = "_QFlogical_cstEid2"} -> !fir.ref>>>> + %4 = fir.declare %0 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFlogical_cstEid2"} : (!fir.ref>>>>) -> !fir.ref>>>> + cuf.data_transfer %false to %4 {transfer_kind = #cuf.cuda_transfer} : i1, !fir.ref>>>> + return +} + +// CHECK-LABEL: func.func @_QPlogical_cst() +// CHECK: %[[DESC:.*]] = fir.alloca !fir.box> +// CHECK: %[[CONST:.*]] = fir.alloca !fir.logical<4> +// CHECK: %[[CONV:.*]] = fir.convert %false : (i1) -> !fir.logical<4> +// CHECK: fir.store %[[CONV]] to %[[CONST]] : !fir.ref> +// CHECK: %[[EMBOX:.*]] = fir.embox %[[CONST]] : (!fir.ref>) -> !fir.box> +// CHECK: fir.store %[[EMBOX]] to %[[DESC]] : !fir.ref>> +// CHECK: %[[BOX_NONE:.*]] = fir.convert %[[DESC]] : (!fir.ref>>) -> !fir.ref> +// CHECK: fir.call @_FortranACUFDataTransferCstDesc(%{{.*}}, %[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none + +func.func @_QPcallkernel(%arg0: !fir.box>> {fir.bindc_name = "a"}, %arg1: !fir.ref {fir.bindc_name = "b"}, %arg2: !fir.ref {fir.bindc_name = "c"}) { + %c0_i64 = arith.constant 0 : i64 + %c1_i32 = arith.constant 1 : i32 + %c0_i32 = arith.constant 0 : i32 + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.dummy_scope : !fir.dscope + %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "_QFcallkernelEa"} : (!fir.box>>, !fir.dscope) -> !fir.box>> + %2 = fir.rebox %1 : (!fir.box>>) -> !fir.box>> + %3 = cuf.alloc !fir.box>>> {bindc_name = "adev", data_attr = #cuf.cuda, uniq_name = "_QFcallkernelEadev"} -> !fir.ref>>>> + %7 = fir.declare %3 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFcallkernelEadev"} : (!fir.ref>>>>) -> !fir.ref>>>> + %8 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFcallkernelEb"} : (!fir.ref, !fir.dscope) -> !fir.ref + %9 = fir.declare %arg2 dummy_scope %0 {uniq_name = "_QFcallkernelEc"} : (!fir.ref, !fir.dscope) -> !fir.ref + %10 = fir.alloca i32 {bindc_name = "m", uniq_name = "_QFcallkernelEm"} + %11 = fir.declare %10 {uniq_name = "_QFcallkernelEm"} : (!fir.ref) -> !fir.ref + %12 = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFcallkernelEn"} + %13 = fir.declare %12 {uniq_name = "_QFcallkernelEn"} : (!fir.ref) -> !fir.ref + %14:3 = fir.box_dims %2, %c0 : (!fir.box>>, index) -> (index, index, index) + %15 = fir.convert %14#1 : (index) -> i32 + fir.store %15 to %13 : !fir.ref + %16:3 = fir.box_dims %2, %c1 : (!fir.box>>, index) -> (index, index, index) + %27 = fir.load %13 : !fir.ref + %28 = fir.convert %27 : (i32) -> index + %29 = arith.cmpi sgt, %28, %c0 : index + %30 = arith.select %29, %28, %c0 : index + %31 = fir.load %11 : !fir.ref + %32 = fir.convert %31 : (i32) -> index + %33 = arith.cmpi sgt, %32, %c0 : index + %34 = arith.select %33, %32, %c0 : index + %35 = fir.shape %30, %34 : (index, index) -> !fir.shape<2> + %36 = fir.undefined index + %37 = fir.slice %c1, %28, %c1, %c1, %32, %c1 : (index, index, index, index, index, index) -> !fir.slice<2> + %38 = fir.rebox %2 [%37] : (!fir.box>>, !fir.slice<2>) -> !fir.box>> + cuf.data_transfer %38 to %7 {transfer_kind = #cuf.cuda_transfer} : !fir.box>>, !fir.ref>>>> + return +} + +// CHECK-LABEL: func.func @_QPcallkernel( +// CHECK-SAME: %[[ARG0:.*]]: !fir.box>> {fir.bindc_name = "a"} +// CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box>> +// CHECK: %[[DECL_ARG0:.*]] = fir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFcallkernelEa"} : (!fir.box>>, !fir.dscope) -> !fir.box>> +// CHECK: %[[REBOX0:.*]] = fir.rebox %[[DECL_ARG0]] : (!fir.box>>) -> !fir.box>> +// CHECK: %[[REBOX1:.*]] = fir.rebox %[[REBOX0]] [%{{.*}}] : (!fir.box>>, !fir.slice<2>) -> !fir.box>> +// CHECK: fir.store %[[REBOX1]] to %[[ALLOCA]] : !fir.ref>>> +// CHECK: %[[BOX_NONE:.*]] = fir.convert %[[ALLOCA]] : (!fir.ref>>>) -> !fir.ref> +// CHECK: fir.call @_FortranACUFDataTransferDescDesc(%{{.*}}, %[[BOX_NONE]], %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, !fir.ref>, i32, !fir.ref, i32) -> none + +func.func @_QPsrc_cst() { + %0 = fir.dummy_scope : !fir.dscope + %1 = cuf.alloc !fir.box>> {bindc_name = "d4", data_attr = #cuf.cuda, uniq_name = "_QFsub4Ed4"} -> !fir.ref>>> + %5:2 = hlfir.declare %1 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFsub4Ed4"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) + %6 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsub4Ei"} + %7:2 = hlfir.declare %6 {uniq_name = "_QFsub4Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c1 = arith.constant 1 : index + %c10_i32 = arith.constant 10 : i32 + %c0_i32 = arith.constant 0 : i32 + %9 = fir.convert %5#1 : (!fir.ref>>>) -> !fir.ref> + %c6_i32 = arith.constant 6 : i32 + %14 = fir.convert %c6_i32 : (i32) -> index + %c10_i32_0 = arith.constant 10 : i32 + %15 = fir.convert %c10_i32_0 : (i32) -> index + %c1_1 = arith.constant 1 : index + %16 = fir.convert %14 : (index) -> i32 + %17:2 = fir.do_loop %arg1 = %14 to %15 step %c1_1 iter_args(%arg2 = %16) -> (index, i32) { + fir.store %arg2 to %7#1 : !fir.ref + %cst = arith.constant -4.000000e+00 : f32 + %22 = fir.load %5#0 : !fir.ref>>> + %23 = fir.load %7#0 : !fir.ref + %24 = fir.convert %23 : (i32) -> i64 + %25 = hlfir.designate %22 (%24) : (!fir.box>>, i64) -> !fir.ref + cuf.data_transfer %cst to %25 {transfer_kind = #cuf.cuda_transfer} : f32, !fir.ref + %26 = arith.addi %arg1, %c1_1 : index + %27 = fir.convert %c1_1 : (index) -> i32 + %28 = fir.load %7#1 : !fir.ref + %29 = arith.addi %28, %27 : i32 + fir.result %26, %29 : index, i32 + } + return +} + +// CHECK-LABEL: func.func @_QPsrc_cst() +// CHECK: %[[ALLOCA:.*]] = fir.alloca f32 +// CHECK: %[[CST:.*]] = arith.constant -4.000000e+00 : f32 +// CHECK: fir.store %[[CST]] to %[[ALLOCA]] : !fir.ref +// CHECK: %[[CONV:.*]] = fir.convert %[[ALLOCA]] : (!fir.ref) -> !fir.llvm_ptr +// CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%{{.*}}, %[[CONV]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> none } // end of module diff --git a/flang/test/Fir/CUDA/cuda-device-global.f90 b/flang/test/Fir/CUDA/cuda-device-global.f90 index c83a938d5af214121533a95e90707754505b5fba..8cac643b27c349650f8bb546b349d70329282bf2 100644 --- a/flang/test/Fir/CUDA/cuda-device-global.f90 +++ b/flang/test/Fir/CUDA/cuda-device-global.f90 @@ -5,9 +5,9 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module} { fir.global @_QMmtestsEn(dense<[3, 4, 5, 6, 7]> : tensor<5xi32>) {data_attr = #cuf.cuda} : !fir.array<5xi32> - gpu.module @cuda_device_mod [#nvvm.target] { + gpu.module @cuda_device_mod { } } -// CHECK: gpu.module @cuda_device_mod [#nvvm.target] +// CHECK: gpu.module @cuda_device_mo // CHECK-NEXT: fir.global @_QMmtestsEn(dense<[3, 4, 5, 6, 7]> : tensor<5xi32>) {data_attr = #cuf.cuda} : !fir.array<5xi32> diff --git a/flang/test/Fir/CUDA/cuda-extranal-mangling.mlir b/flang/test/Fir/CUDA/cuda-extranal-mangling.mlir new file mode 100644 index 0000000000000000000000000000000000000000..551a89a7018c2867effb5126560e8e005c1e4a0a --- /dev/null +++ b/flang/test/Fir/CUDA/cuda-extranal-mangling.mlir @@ -0,0 +1,13 @@ +// RUN: fir-opt --split-input-file --external-name-interop %s | FileCheck %s + +gpu.module @cuda_device_mod { + gpu.func @_QPfoo() { + fir.call @_QPthreadfence() fastmath : () -> () + gpu.return + } + func.func private @_QPthreadfence() attributes {cuf.proc_attr = #cuf.cuda_proc} +} + +// CHECK-LABEL: gpu.func @_QPfoo +// CHECK: fir.call @threadfence_() +// CHECK: func.func private @threadfence_() diff --git a/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 b/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 index 18b56a491cd65f1b9c551df598e707c7ee175656..772e2696171a63016bbcc3c0f09383cef61dff38 100644 --- a/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 +++ b/flang/test/Fir/CUDA/cuda-implicit-device-global.f90 @@ -25,7 +25,7 @@ fir.global linkonce @_QQclX6995815537abaf90e86ce166af128f3a constant : !fir.char // CHECK: fir.call @_FortranAioBeginExternalListOutput(%{{.*}}, %[[CONV]], %{{.*}}) fastmath : (i32, !fir.ref, i32) -> !fir.ref // CHECK: fir.global linkonce @_QQcl[[SYMBOL]] {data_attr = #cuf.cuda} constant : !fir.char<1,32> -// CHECK-LABEL: gpu.module @cuda_device_mod [#nvvm.target] +// CHECK-LABEL: gpu.module @cuda_device_mod // CHECK: fir.global linkonce @_QQclX6995815537abaf90e86ce166af128f3a // ----- @@ -51,5 +51,96 @@ fir.global linkonce @_QQclX6995815537abaf90e86ce166af128f3a constant : !fir.char // CHECK: fir.call @_FortranAioBeginExternalListOutput(%{{.*}}, %[[CONV]], %{{.*}}) fastmath : (i32, !fir.ref, i32) -> !fir.ref // CHECK: fir.global linkonce @_QQcl[[SYMBOL]] constant : !fir.char<1,32> -// CHECK-LABEL: gpu.module @cuda_device_mod [#nvvm.target] +// CHECK-LABEL: gpu.module @cuda_device_mod // CHECK-NOT: fir.global linkonce @_QQclX6995815537abaf90e86ce166af128f3a + +// ----- + +func.func @_QPsub1() { + %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsub1Ei"} + %1:2 = hlfir.declare %0 {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %c1_i32 = arith.constant 1 : i32 + %2 = fir.convert %c1_i32 : (i32) -> index + %c100_i32 = arith.constant 100 : i32 + %3 = fir.convert %c100_i32 : (i32) -> index + %c1 = arith.constant 1 : index + cuf.kernel<<<*, *>>> (%arg0 : index) = (%2 : index) to (%3 : index) step (%c1 : index) { + %4 = fir.convert %arg0 : (index) -> i32 + fir.store %4 to %1#1 : !fir.ref + %5 = fir.load %1#0 : !fir.ref + %c1_i32_0 = arith.constant 1 : i32 + %6 = arith.cmpi eq, %5, %c1_i32_0 : i32 + fir.if %6 { + %c6_i32 = arith.constant 6 : i32 + %7 = fir.address_of(@_QQclX91d13f6e74caa2f03965d7a7c6a8fdd5) : !fir.ref> + %8 = fir.convert %7 : (!fir.ref>) -> !fir.ref + %c5_i32 = arith.constant 5 : i32 + %9 = fir.call @_FortranAioBeginExternalListOutput(%c6_i32, %8, %c5_i32) fastmath : (i32, !fir.ref, i32) -> !fir.ref + %10 = fir.address_of(@_QQclX5465737420504153534544) : !fir.ref> + %c11 = arith.constant 11 : index + %11:2 = hlfir.declare %10 typeparams %c11 {fortran_attrs = #fir.var_attrs, uniq_name = "_QQclX5465737420504153534544"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) + %12 = fir.convert %11#1 : (!fir.ref>) -> !fir.ref + %13 = fir.convert %c11 : (index) -> i64 + %14 = fir.call @_FortranAioOutputAscii(%9, %12, %13) fastmath : (!fir.ref, !fir.ref, i64) -> i1 + %15 = fir.call @_FortranAioEndIoStatement(%9) fastmath : (!fir.ref) -> i32 + } + "fir.end"() : () -> () + } + return +} +func.func private @_FortranAioBeginExternalListOutput(i32, !fir.ref, i32) -> !fir.ref attributes {fir.io, fir.runtime} +fir.global linkonce @_QQclX91d13f6e74caa2f03965d7a7c6a8fdd5 constant : !fir.char<1,10> { + %0 = fir.string_lit "dummy.cuf\00"(10) : !fir.char<1,10> + fir.has_value %0 : !fir.char<1,10> +} +func.func private @_FortranAioOutputAscii(!fir.ref, !fir.ref, i64) -> i1 attributes {fir.io, fir.runtime} +fir.global linkonce @_QQclX5465737420504153534544 constant : !fir.char<1,11> { + %0 = fir.string_lit "Test PASSED"(11) : !fir.char<1,11> + fir.has_value %0 : !fir.char<1,11> +} + +// CHECK: fir.global linkonce @_QQclX5465737420504153534544 {data_attr = #cuf.cuda} constant : !fir.char<1,11> + +// CHECK-LABEL: gpu.module @cuda_device_mod +// CHECK: fir.global linkonce @_QQclX5465737420504153534544 {data_attr = #cuf.cuda} constant + +// ----- + +func.func @_QPsub1() attributes {cuf.proc_attr = #cuf.cuda_proc} { + %6 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsub1Ei"} + %7:2 = hlfir.declare %6 {uniq_name = "_QFsub1Ei"} : (!fir.ref) -> (!fir.ref, !fir.ref) + %12 = fir.load %7#0 : !fir.ref + %c1_i32 = arith.constant 1 : i32 + %13 = arith.cmpi eq, %12, %c1_i32 : i32 + fir.if %13 { + %c6_i32 = arith.constant 6 : i32 + %14 = fir.address_of(@_QQclX91d13f6e74caa2f03965d7a7c6a8fdd5) : !fir.ref> + %15 = fir.convert %14 : (!fir.ref>) -> !fir.ref + %c3_i32 = arith.constant 3 : i32 + %16 = fir.call @_FortranAioBeginExternalListOutput(%c6_i32, %15, %c3_i32) fastmath : (i32, !fir.ref, i32) -> !fir.ref + %17 = fir.address_of(@_QQclX5465737420504153534544) : !fir.ref> + %c11 = arith.constant 11 : index + %18:2 = hlfir.declare %17 typeparams %c11 {fortran_attrs = #fir.var_attrs, uniq_name = "_QQclX5465737420504153534544"} : (!fir.ref>, index) -> (!fir.ref>, !fir.ref>) + %19 = fir.convert %18#1 : (!fir.ref>) -> !fir.ref + %20 = fir.convert %c11 : (index) -> i64 + %21 = fir.call @_FortranAioOutputAscii(%16, %19, %20) fastmath : (!fir.ref, !fir.ref, i64) -> i1 + %22 = fir.call @_FortranAioEndIoStatement(%16) fastmath : (!fir.ref) -> i32 + } + return +} +func.func private @_FortranAioBeginExternalListOutput(i32, !fir.ref, i32) -> !fir.ref attributes {fir.io, fir.runtime} +fir.global linkonce @_QQclX91d13f6e74caa2f03965d7a7c6a8fdd5 constant : !fir.char<1,10> { + %0 = fir.string_lit "dummy.cuf\00"(10) : !fir.char<1,10> + fir.has_value %0 : !fir.char<1,10> +} +func.func private @_FortranAioOutputAscii(!fir.ref, !fir.ref, i64) -> i1 attributes {fir.io, fir.runtime} +fir.global linkonce @_QQclX5465737420504153534544 constant : !fir.char<1,11> { + %0 = fir.string_lit "Test PASSED"(11) : !fir.char<1,11> + fir.has_value %0 : !fir.char<1,11> +} +func.func private @_FortranAioEndIoStatement(!fir.ref) -> i32 attributes {fir.io, fir.runtime} + +// CHECK: fir.global linkonce @_QQclX5465737420504153534544 {data_attr = #cuf.cuda} constant : !fir.char<1,11> + +// CHECK-LABEL: gpu.module @cuda_device_mod +// CHECK: fir.global linkonce @_QQclX5465737420504153534544 {data_attr = #cuf.cuda} constant diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index bca454c13ff9cc6971385911fd4453965db06bbd..4b18acb7c2b4301387ce0a04376ac2a7f32e0e2b 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -47,6 +47,7 @@ func.func @_QQmain() { // PASSES-NEXT: LowerHLFIRIntrinsics // PASSES-NEXT: BufferizeHLFIR // PASSES-NEXT: ConvertHLFIRtoFIR +// PASSES-NEXT: LowerWorkshare // PASSES-NEXT: CSE // PASSES-NEXT: (S) 0 num-cse'd - Number of operations CSE'd // PASSES-NEXT: (S) 0 num-dce'd - Number of operations DCE'd diff --git a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir index 184abe24fe967d74c0604552bd5b90373b6c7201..6e4ac824fbd9cf824ac23257622473338b69acfa 100644 --- a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir +++ b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir @@ -985,8 +985,8 @@ func.func @omp_map_info_nested_derived_type_explicit_member_conversion(%arg0 : ! %6 = fir.coordinate_of %arg0, %5 : (!fir.ref,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>>, !fir.field) -> !fir.ref // CHECK: %[[MAP_MEMBER_2:.*]] = omp.map.info var_ptr(%[[GEP_3]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr %7 = omp.map.info var_ptr(%6 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref - // CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.struct<"_QFTtop_layer", (array<10 x i32>, struct<"_QFTbottom_layer", (array<10 x f32>, f64)>, i32)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_1]], %[[MAP_MEMBER_2]] : [1,1], [2,-1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {partial_map = true} - %9 = omp.map.info var_ptr(%arg0 : !fir.ref,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>>, !fir.type<_QFTtop_layer{array_i:!fir.array<10xi32>,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>) map_clauses(tofrom) capture(ByRef) members(%4, %7 : [1,1], [2,-1] : !fir.ref, !fir.ref) -> !fir.ref,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>> {partial_map = true} + // CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.struct<"_QFTtop_layer", (array<10 x i32>, struct<"_QFTbottom_layer", (array<10 x f32>, f64)>, i32)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_1]], %[[MAP_MEMBER_2]] : [1, 1], [2] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {partial_map = true} + %9 = omp.map.info var_ptr(%arg0 : !fir.ref,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>>, !fir.type<_QFTtop_layer{array_i:!fir.array<10xi32>,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>) map_clauses(tofrom) capture(ByRef) members(%4, %7 : [1,1], [2] : !fir.ref, !fir.ref) -> !fir.ref,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>> {partial_map = true} // CHECK: omp.target map_entries(%[[MAP_MEMBER_1]] -> %{{.*}}, %[[MAP_MEMBER_2]] -> %{{.*}}, %[[PARENT_MAP]] -> %{{.*}} : !llvm.ptr, !llvm.ptr, !llvm.ptr) { omp.target map_entries(%4 -> %arg1, %7 -> %arg2, %9 -> %arg3 : !fir.ref, !fir.ref, !fir.ref,nested:!fir.type<_QFTbottom_layer{array_i2:!fir.array<10xf32>,i2:f64}>,k:i32}>>) { omp.terminator @@ -1065,3 +1065,213 @@ func.func @omp_map_common_block_using_common_block_members() { } fir.global common @var_common_(dense<0> : vector<8xi8>) {alignment = 4 : i64} : !fir.array<8xi8> + +// ----- + + +func.func @use_string(%arg0 : !fir.ref>) { + return +} + +func.func @use_index(%arg0 : index) { + return +} + +// CHECK-LABEL: llvm.func @alloca_hoisting_openmp() { +// CHECK: %[[VAL_0:.*]] = llvm.mlir.constant(6 : index) : i64 +// CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(1 : i32) : i32 +// CHECK: %[[VAL_2:.*]] = llvm.mlir.constant(42 : i32) : i32 +// CHECK: omp.parallel { +// CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(6 : index) : i64 +// CHECK: %[[VAL_4:.*]] = llvm.alloca %[[VAL_3]] x i8 : (i64) -> !llvm.ptr +// CHECK: omp.wsloop { +// CHECK: omp.loop_nest (%[[VAL_5:.*]]) : i32 = (%[[VAL_1]]) to (%[[VAL_2]]) inclusive step (%[[VAL_1]]) { +// CHECK: %[[VAL_6:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: llvm.call @use_string(%[[VAL_4]]) : (!llvm.ptr) -> () +// CHECK: omp.yield +// CHECK: } +// CHECK: } +// CHECK: omp.terminator +// CHECK: } +// CHECK: llvm.call @use_index(%[[VAL_0]]) : (i64) -> () +// CHECK: llvm.return +// CHECK: } +func.func @alloca_hoisting_openmp() { + %c6 = arith.constant 6 : index + %c1_i32 = arith.constant 1 : i32 + %c42_i32 = arith.constant 42 : i32 + omp.parallel { + omp.wsloop { + omp.loop_nest (%arg0) : i32 = (%c1_i32) to (%c42_i32) inclusive step (%c1_i32) { + %0 = fir.alloca !fir.char<1,?>(%c6 : index) + fir.call @use_string(%0) : (!fir.ref>) -> () + omp.yield + } + } + omp.terminator + } + fir.call @use_index(%c6) : (index) -> () + return +} + +// ----- + +// NOTE: This test (and the other allocatable member map tests below) uses mock +// bounds to simplify the example, the real bounds generation is more complex +// as it has to access the box information. However, it's not what the test +// aims to check. The test aims to check the parent member bindings and +// acceses are appropriately maintained when lowering to the LLVM dialect. + +// CHECK-LABEL: llvm.func @map_dtype_alloca_mem +// CHECK-SAME: %[[ARG_0:.*]]: !llvm.ptr) +func.func @map_dtype_alloca_mem(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) { + %c4 = arith.constant 4 : index + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + // CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} + %0 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%c4 : index) extent(%c4 : index) stride(%c1 : index) start_idx(%c0 : index) {stride_in_bytes = true} + // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ARG_0]][0, 4] : (!llvm.ptr) -> !llvm.ptr, [[STRUCT_TY:!llvm.struct<"_QFRecTy", \(f32, struct<\(ptr, i64, i32, i8, i8, i8, i8\)>, array<10 x i32>, f32, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32\)>]] + %1 = fir.coordinate_of %arg0, %c4 : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>, index) -> !fir.ref>>> + // CHECK: %[[BADDR_GEP:.*]] = llvm.getelementptr %[[GEP]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[STRUCT_TY2:!llvm.struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>]] + %2 = fir.box_offset %1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_MEMBER_BADDR:.*]] = omp.map.info var_ptr(%[[GEP]] : !llvm.ptr, i32) var_ptr_ptr(%[[BADDR_GEP]] : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr + %3 = omp.map.info var_ptr(%1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%2 : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%0) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[GEP]] : !llvm.ptr, [[STRUCT_TY2]]) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %4 = omp.map.info var_ptr(%1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref>>> + // CHECK: %[[MAP_PARENT_DTYPE:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, [[STRUCT_TY]]) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_DESCRIPTOR]], %[[MAP_MEMBER_BADDR]] : [4], [4, 0] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {partial_map = true} + %5 = omp.map.info var_ptr(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>, !fir.type<_QFRecTy{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>) map_clauses(tofrom) capture(ByRef) members(%4, %3 : [4], [4,0] : !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>> {partial_map = true} + // CHECK: omp.target map_entries(%[[MAP_MEMBER_DESCRIPTOR]] -> %[[ARG_1:.*]], %[[MAP_MEMBER_BADDR]] -> %[[ARG_2:.*]], %[[MAP_PARENT_DTYPE]] -> %[[ARG_3:.*]] : !llvm.ptr, !llvm.ptr, !llvm.ptr) { + omp.target map_entries(%4 -> %arg1, %3 -> %arg2, %5 -> %arg3 : !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) { + omp.terminator + } + return +} + +// ----- + +// CHECK-LABEL: llvm.func @map_dtype_alloca_mem2 +// CHECK-SAME: %[[ARG_0:.*]]: !llvm.ptr) +func.func @map_dtype_alloca_mem2(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) { + // CHECK: %[[DTYPE_ALLOCATABLE_ALOCA_2:.*]] = llvm.alloca {{.*}} x [[DESC_TY:!llvm.struct<\(ptr, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>\)>]] {alignment = 8 : i64} : (i32) -> !llvm.ptr + // CHECK: %[[DTYPE_ALLOCATABLE_ALOCA:.*]] = llvm.alloca {{.*}} x [[DESC_TY]] {alignment = 8 : i64} : (i32) -> !llvm.ptr + %c5 = arith.constant 5 : index + %c4 = arith.constant 4 : index + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + // CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} + %0 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%c4 : index) extent(%c4 : index) stride(%c1 : index) start_idx(%c0 : index) {stride_in_bytes = true} + // CHECK: "llvm.intr.memcpy"(%[[DTYPE_ALLOCATABLE_ALOCA]], %[[ARG_0]], {{.*}}) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () + %1 = fir.load %arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> + // CHECK: %[[GEP_DTYPE_BADDR:.*]] = llvm.getelementptr %[[DTYPE_ALLOCATABLE_ALOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY]] + // CHECK: %[[LOAD_DTYPE_BADDR:.*]] = llvm.load %[[GEP_DTYPE_BADDR]] : !llvm.ptr -> !llvm.ptr + // CHECK: %[[GEP_DTYPE_MEMBER:.*]] = llvm.getelementptr %[[LOAD_DTYPE_BADDR]][0, 4] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY:!llvm.struct<"_QFRecTy", \(f32, struct<\(ptr, i64, i32, i8, i8, i8, i8\)>, array<10 x i32>, f32, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32\)>]] + %2 = fir.coordinate_of %1, %c4 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>, index) -> !fir.ref>>> + // CHECK: %[[DTYPE_MEMBER_BADDR:.*]] = llvm.getelementptr %[[GEP_DTYPE_MEMBER]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY2:!llvm.struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>]] + %3 = fir.box_offset %2 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_MEMBER_BADDR:.*]] = omp.map.info var_ptr(%[[GEP_DTYPE_MEMBER]] : !llvm.ptr, i32) var_ptr_ptr(%[[DTYPE_MEMBER_BADDR]] : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr + %4 = omp.map.info var_ptr(%2 : !fir.ref>>>, !fir.array) var_ptr_ptr(%3 : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%0) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[GEP_DTYPE_MEMBER]] : !llvm.ptr, [[DESC_TY2]]) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %5 = omp.map.info var_ptr(%2 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref>>> + // CHECK: "llvm.intr.memcpy"(%[[DTYPE_ALLOCATABLE_ALOCA_2]], %[[ARG_0]], {{.*}}) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () + %6 = fir.load %arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> + // CHECK: %[[GEP_DTYPE_BADDR:.*]] = llvm.getelementptr %[[DTYPE_ALLOCATABLE_ALOCA_2]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY]] + // CHECK: %[[LOAD_DTYPE_BADDR:.*]] = llvm.load %[[GEP_DTYPE_BADDR]] : !llvm.ptr -> !llvm.ptr + // CHECK: %[[GEP_DTYPE_REGULAR_MEMBER:.*]] = llvm.getelementptr %[[LOAD_DTYPE_BADDR]][0, 5] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY]] + %7 = fir.coordinate_of %6, %c5 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>, index) -> !fir.ref + // CHECK: %[[MAP_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[GEP_DTYPE_REGULAR_MEMBER]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %8 = omp.map.info var_ptr(%7 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref + // CHECK: %[[GEP_DTYPE_BADDR:.*]] = llvm.getelementptr %[[ARG_0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY]] + %9 = fir.box_offset %arg0 base_addr : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) -> !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>> + // CHECK: %[[MAP_DTYPE_PARENT_BADDR:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, [[REC_TY]]) var_ptr_ptr(%[[GEP_DTYPE_BADDR]] : !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %10 = omp.map.info var_ptr(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>, !fir.type<_QFRecTy{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>) var_ptr_ptr(%9 : !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>> + // CHECK: %[[MAP_DTYPE_PARENT_DESC:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, [[DESC_TY]]) map_clauses(tofrom) capture(ByRef) members(%[[MAP_DTYPE_PARENT_BADDR]], %[[MAP_MEMBER_DESC]], %[[MAP_MEMBER_BADDR]], %[[MAP_REGULAR_MEMBER]] : [0], [0, 4], [0, 4, 0], [0, 5] : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> !llvm.ptr + %11 = omp.map.info var_ptr(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>, !fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>) map_clauses(tofrom) capture(ByRef) members(%10, %5, %4, %8 : [0], [0,4], [0,4,0], [0,5] : !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> + // CHECK: omp.target map_entries(%[[MAP_DTYPE_PARENT_BADDR]] -> %[[ARG_1:.*]], %[[MAP_MEMBER_DESC]] -> %[[ARG_2:.*]], %[[MAP_MEMBER_BADDR]] -> %[[ARG_3:.*]], %[[MAP_REGULAR_MEMBER]] -> %[[ARG_4:.*]], %[[MAP_DTYPE_PARENT_DESC]] -> %[[ARG_5:.*]] : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) { + omp.target map_entries(%10 -> %arg1, %5 -> %arg2, %4 -> %arg3, %8 -> %arg4, %11 -> %arg5 : !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) { + omp.terminator + } + return +} + +// ----- + +// CHECK-LABEL: llvm.func @map_nested_dtype_alloca_mem +// CHECK-SAME: %[[ARG_0:.*]]: !llvm.ptr) +func.func @map_nested_dtype_alloca_mem(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) { + // CHECK: %[[DTYPE_ALLOCATABLE_ALOCA_2:.*]] = llvm.alloca {{.*}} x [[DESC_TY:!llvm.struct<\(ptr, i64, i32, i8, i8, i8, i8, ptr, array<1 x i64>\)>]] {alignment = 8 : i64} : (i32) -> !llvm.ptr + // CHECK: %[[DTYPE_ALLOCATABLE_ALOCA:.*]] = llvm.alloca {{.*}} x [[DESC_TY]] {alignment = 8 : i64} : (i32) -> !llvm.ptr + %c3 = arith.constant 3 : index + %c4 = arith.constant 4 : index + %c6 = arith.constant 6 : index + %c1 = arith.constant 1 : index + %c2 = arith.constant 2 : index + %c0 = arith.constant 0 : index + // CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} + %0 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%c4 : index) extent(%c4 : index) stride(%c1 : index) start_idx(%c0 : index) {stride_in_bytes = true} + // CHECK: "llvm.intr.memcpy"(%[[DTYPE_ALLOCATABLE_ALOCA]], %[[ARG_0]], {{.*}}) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () + %1 = fir.load %arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> + // CHECK: %[[GEP_DTYPE_BADDR:.*]] = llvm.getelementptr %[[DTYPE_ALLOCATABLE_ALOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY]] + // CHECK: %[[LOAD_GEP_DTYPE_BADDR:.*]] = llvm.load %[[GEP_DTYPE_BADDR]] : !llvm.ptr -> !llvm.ptr + // CHECK: %[[LOAD_NESTED_DTYPE:.*]] = llvm.getelementptr %[[LOAD_GEP_DTYPE_BADDR]][0, 6] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY:!llvm.struct<"_QFRecTy", \(f32, struct<\(ptr, i64, i32, i8, i8, i8, i8\)>, array<10 x i32>, f32, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32, struct<"_QFRecTy2", \(f32, array<10 x i32>, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32\)>\)>]] + %2 = fir.coordinate_of %1, %c6 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + // CHECK: %[[GEP_NESTED_DTYPE_ALLOCATABLE_MEMBER:.*]] = llvm.getelementptr %[[LOAD_NESTED_DTYPE]][0, 2] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY2:!llvm.struct<"_QFRecTy2", \(f32, array<10 x i32>, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32\)>]] + %3 = fir.coordinate_of %2, %c2 : (!fir.ref,array_k:!fir.box>>,k:i32}>>, index) -> !fir.ref>>> + // CHECK: %[[GEP_NESTED_DTYPE_ALLOCATABLE_MEMBER_BADDR:.*]] = llvm.getelementptr %[[GEP_NESTED_DTYPE_ALLOCATABLE_MEMBER]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY2:!llvm.struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>]] + %4 = fir.box_offset %3 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_NESTED_MEMBER_BADDR:.*]] = omp.map.info var_ptr(%[[GEP_NESTED_DTYPE_ALLOCATABLE_MEMBER]] : !llvm.ptr, i32) var_ptr_ptr(%[[GEP_NESTED_DTYPE_ALLOCATABLE_MEMBER_BADDR]] : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr + %5 = omp.map.info var_ptr(%3 : !fir.ref>>>, !fir.array) var_ptr_ptr(%4 : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%0) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_NESTED_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[GEP_NESTED_DTYPE_ALLOCATABLE_MEMBER]] : !llvm.ptr, [[DESC_TY2]]) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %6 = omp.map.info var_ptr(%3 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref>>> + // CHECK: "llvm.intr.memcpy"(%[[DTYPE_ALLOCATABLE_ALOCA_2]], %[[ARG_0]], {{.*}}) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () + // CHECK: %[[GEP_DTYPE_BADDR:.*]] = llvm.getelementptr %[[DTYPE_ALLOCATABLE_ALOCA_2]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY]] + // CHECK: %[[LOAD_GEP_DTYPE_BADDR:.*]] = llvm.load %[[GEP_DTYPE_BADDR]] : !llvm.ptr -> !llvm.ptr + %7 = fir.load %arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> + // CHECK: %[[LOAD_NESTED_DTYPE:.*]] = llvm.getelementptr %[[LOAD_GEP_DTYPE_BADDR]][0, 6] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY]] + %8 = fir.coordinate_of %7, %c6 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + // CHECK: %[[NESTED_DTYPE_REGULAR_MEMBER_GEP:.*]] = llvm.getelementptr %[[LOAD_NESTED_DTYPE]][0, 3] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY2]] + %9 = fir.coordinate_of %8, %c3 : (!fir.ref,array_k:!fir.box>>,k:i32}>>, index) -> !fir.ref + // CHECK: %[[MAP_REGULAR_NESTED_MEMBER:.*]] = omp.map.info var_ptr(%[[NESTED_DTYPE_REGULAR_MEMBER_GEP]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %10 = omp.map.info var_ptr(%9 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref + // CHECK: %[[DTYPE_BADDR_GEP:.*]] = llvm.getelementptr %[[ARG_0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY]] + %11 = fir.box_offset %arg0 base_addr : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) -> !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>> + // CHECK: %[[MAP_PARENT_BADDR:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, [[REC_TY]]) var_ptr_ptr(%[[DTYPE_BADDR_GEP]] : !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %12 = omp.map.info var_ptr(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>, !fir.type<_QFRecTy{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>) var_ptr_ptr(%11 : !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>> + // CHECK: %[[MAP_PARENT_DESC:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, [[DESC_TY]]) map_clauses(tofrom) capture(ByRef) members(%[[MAP_PARENT_BADDR]], %[[MAP_NESTED_MEMBER_DESC]], %[[MAP_NESTED_MEMBER_BADDR]], %[[MAP_REGULAR_NESTED_MEMBER]] : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> !llvm.ptr + %13 = omp.map.info var_ptr(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>, !fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>) map_clauses(tofrom) capture(ByRef) members(%12, %6, %5, %10 : [0], [0,6,2], [0,6,2,0], [0,6,3] : !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> + // CHECK: omp.target map_entries(%[[MAP_PARENT_BADDR]] -> %[[ARG_1:.*]], %[[MAP_NESTED_MEMBER_DESC]] -> %[[ARG_2:.*]], %[[MAP_NESTED_MEMBER_BADDR]] -> %[[ARG_3:.*]], %[[MAP_REGULAR_NESTED_MEMBER]] -> %[[ARG_4:.*]], %[[MAP_PARENT_DESC]] -> %[[ARG_5:.*]] : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) { + omp.target map_entries(%12 -> %arg1, %6 -> %arg2, %5 -> %arg3, %10 -> %arg4, %13 -> %arg5 : !fir.llvm_ptr>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) { + omp.terminator + } + return +} + +// ----- + +// CHECK-LABEL: llvm.func @map_nested_dtype_alloca_mem2 +// CHECK-SAME: %[[ARG_0:.*]]: !llvm.ptr) +func.func @map_nested_dtype_alloca_mem2(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) { + %c4 = arith.constant 4 : index + %c1 = arith.constant 1 : index + %c2 = arith.constant 2 : index + %c0 = arith.constant 0 : index + %c6 = arith.constant 6 : index + // CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} + %0 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%c4 : index) extent(%c4 : index) stride(%c1 : index) start_idx(%c0 : index) {stride_in_bytes = true} + // CHECK: %[[NESTED_DTYPE_MEMBER_GEP:.*]] = llvm.getelementptr %[[ARG_0]][0, 6] : (!llvm.ptr) -> !llvm.ptr, [[REC_TY:!llvm.struct<"_QFRecTy", \(f32, struct<\(ptr, i64, i32, i8, i8, i8, i8\)>, array<10 x i32>, f32, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32, struct<"_QFRecTy2", \(f32, array<10 x i32>, struct<\(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>\)>, i32\)>\)>]] + %1 = fir.coordinate_of %arg0, %c6 : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + // CHECK: %[[NESTED_ALLOCATABLE_MEMBER_GEP:.*]] = llvm.getelementptr %[[NESTED_DTYPE_MEMBER_GEP]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"_QFRecTy2", (f32, array<10 x i32>, struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>, i32)> + %2 = fir.coordinate_of %1, %c2 : (!fir.ref,array_k:!fir.box>>,k:i32}>>, index) -> !fir.ref>>> + // CHECK: %[[NESTED_ALLOCATABLE_MEMBER_BADDR_GEP:.*]] = llvm.getelementptr %[[NESTED_ALLOCATABLE_MEMBER_GEP]][0, 0] : (!llvm.ptr) -> !llvm.ptr, [[DESC_TY2]] + %3 = fir.box_offset %2 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_NESTED_ALLOCATABLE_MEMBER_BADDR:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCATABLE_MEMBER_GEP]] : !llvm.ptr, i32) var_ptr_ptr(%[[NESTED_ALLOCATABLE_MEMBER_BADDR_GEP]] : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr + %4 = omp.map.info var_ptr(%2 : !fir.ref>>>, !fir.array) var_ptr_ptr(%3 : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%0) -> !fir.llvm_ptr>> + // CHECK: %[[MAP_NESTED_ALLOCATABLE_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCATABLE_MEMBER_GEP]] : !llvm.ptr, [[DESC_TY2]]) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %5 = omp.map.info var_ptr(%2 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref>>> + // CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, [[REC_TY]]) map_clauses(tofrom) capture(ByRef) members(%[[MAP_NESTED_ALLOCATABLE_MEMBER_DESC]], %[[MAP_NESTED_ALLOCATABLE_MEMBER_BADDR]] : [6, 2], [6, 2, 0] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {partial_map = true} + %6 = omp.map.info var_ptr(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>, !fir.type<_QFRecTy{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>) map_clauses(tofrom) capture(ByRef) members(%5, %4 : [6,2], [6,2,0] : !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>> {partial_map = true} + // CHECK: omp.target map_entries(%[[MAP_NESTED_ALLOCATABLE_MEMBER_DESC]] -> %[[ARG_1:.*]], %[[MAP_NESTED_ALLOCATABLE_MEMBER_BADDR]] -> %[[ARG_2:.*]], %[[MAP_PARENT]] -> %[[ARG_3:.*]] : !llvm.ptr, !llvm.ptr, !llvm.ptr) { + omp.target map_entries(%5 -> %arg1, %4 -> %arg2, %6 -> %arg3 : !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFRecTy2{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) { + omp.terminator + } + return +} diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir index fa391fa6cc7a7d8f74d57b9d0eb9a9a3b0cd77e6..4c9f965e1241a0c936b9b4f846642ee380fa48dd 100644 --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -2776,3 +2776,19 @@ func.func @coordinate_array_unknown_size_1d(%arg0: !fir.ptr> fir.global common @c_(dense<0> : vector<4294967296xi8>) : !fir.array<4294967296xi8> // CHECK: llvm.mlir.global common @c_(dense<0> : vector<4294967296xi8>) {addr_space = 0 : i32} : !llvm.array<4294967296 x i8> + +// ----- + +gpu.module @cuda_device_mod { + gpu.func @test_alloc_and_freemem_one() { + %z0 = fir.allocmem i32 + fir.freemem %z0 : !fir.heap + gpu.return + } +} + +// CHECK: gpu.module @cuda_device_mod { +// CHECK: llvm.func @free(!llvm.ptr) +// CHECK: llvm.func @malloc(i64) -> !llvm.ptr +// CHECK: llvm.call @malloc +// CHECK: lvm.call @free diff --git a/flang/test/Fir/target-rewrite-complex16.fir b/flang/test/Fir/target-rewrite-complex16.fir index 4f807e828d8f10fc860cdf11f87e5e8c3647e1dc..86a5b0051ab2ed43ff05f0502ed5faa4fb2fce2a 100644 --- a/flang/test/Fir/target-rewrite-complex16.fir +++ b/flang/test/Fir/target-rewrite-complex16.fir @@ -1,4 +1,5 @@ // RUN: fir-opt --target-rewrite="target=x86_64-unknown-linux-gnu" %s | FileCheck %s +// RUN: fir-opt --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s // Test that we rewrite the signature and body of a func.function that returns a // complex<16>. diff --git a/flang/test/Fir/target-rewrite-integer-loongarch64.fir b/flang/test/Fir/target-rewrite-integer-loongarch64.fir new file mode 100644 index 0000000000000000000000000000000000000000..8421cbbb41a9d3708b5c1022cac16db01a484b07 --- /dev/null +++ b/flang/test/Fir/target-rewrite-integer-loongarch64.fir @@ -0,0 +1,27 @@ +/// Test i32 passing and returning on LoongArch64 +/// LoongArch64 LP64D ABI requires unsigned 32 bit integers to be sign extended. + +// REQUIRES: loongarch-registered-target +// RUN: fir-opt --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64 +// RUN: tco -target="loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64_LLVM + +// LOONGARCH64: func.func private @cfunc32(i32 {llvm.signext}) -> (i32 {llvm.signext}) attributes {fir.bindc_name = "cfunc32"} + +// LOONGARCH64_LLVM: declare signext i32 @cfunc32(i32 signext) +func.func private @cfunc32(i32) -> i32 attributes {fir.bindc_name = "cfunc32"} + +// LOONGARCH64-LABEL: func.func @foo( +// LOONGARCH64-SAME: %[[VAL_0:.*]]: i32 {llvm.signext}) -> (i32 {llvm.signext}) attributes {fir.bindc_name = "foo"} { +// LOONGARCH64: %[[VAL_1:.*]] = fir.call @cfunc32(%[[VAL_0]]) fastmath : (i32) -> i32 +// LOONGARCH64: return %[[VAL_1]] : i32 +// LOONGARCH64: } + +// LOONGARCH64_LLVM-LABEL: define signext i32 @foo( +// LOONGARCH64_LLVM: i32 signext %[[VAL_0:.*]]) { +// LOONGARCH64_LLVM: %[[VAL_1:.*]] = call i32 @cfunc32(i32 %[[VAL_0]]) +// LOONGARCH64_LLVM: ret i32 %[[VAL_1]] +// LOONGARCH64_LLVM: } +func.func @foo(%0: i32) -> i32 attributes {fir.bindc_name = "foo"} { + %1 = fir.call @cfunc32(%0) fastmath : (i32) -> i32 + return %1 : i32 +} diff --git a/flang/test/HLFIR/bufferize-workshare.fir b/flang/test/HLFIR/bufferize-workshare.fir new file mode 100644 index 0000000000000000000000000000000000000000..af5abb381937ecf622d07e0b535cb3fd7a503856 --- /dev/null +++ b/flang/test/HLFIR/bufferize-workshare.fir @@ -0,0 +1,57 @@ +// RUN: fir-opt --bufferize-hlfir %s | FileCheck %s + +// CHECK-LABEL: func.func @simple( +// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>) { +// CHECK: omp.parallel { +// CHECK: omp.workshare { +// CHECK: %[[VAL_1:.*]] = arith.constant 42 : index +// CHECK: %[[VAL_2:.*]] = arith.constant 1 : i32 +// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> +// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) +// CHECK: %[[VAL_5:.*]] = fir.allocmem !fir.array<42xi32> {bindc_name = ".tmp.array", uniq_name = ""} +// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_3]]) {uniq_name = ".tmp.array"} : (!fir.heap>, !fir.shape<1>) -> (!fir.heap>, !fir.heap>) +// CHECK: %[[VAL_7:.*]] = arith.constant true +// CHECK: %[[VAL_8:.*]] = arith.constant 1 : index +// CHECK: omp.workshare.loop_wrapper { +// CHECK: omp.loop_nest (%[[VAL_9:.*]]) : index = (%[[VAL_8]]) to (%[[VAL_1]]) inclusive step (%[[VAL_8]]) { +// CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_9]]) : (!fir.ref>, index) -> !fir.ref +// CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref +// CHECK: %[[VAL_12:.*]] = arith.subi %[[VAL_11]], %[[VAL_2]] : i32 +// CHECK: %[[VAL_13:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_9]]) : (!fir.heap>, index) -> !fir.ref +// CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_13]] temporary_lhs : i32, !fir.ref +// CHECK: omp.yield +// CHECK: } +// CHECK: } +// CHECK: %[[VAL_14:.*]] = fir.undefined tuple>, i1> +// CHECK: %[[VAL_15:.*]] = fir.insert_value %[[VAL_14]], %[[VAL_7]], [1 : index] : (tuple>, i1>, i1) -> tuple>, i1> +// CHECK: %[[VAL_16:.*]] = fir.insert_value %[[VAL_15]], %[[VAL_6]]#0, [0 : index] : (tuple>, i1>, !fir.heap>) -> tuple>, i1> +// CHECK: hlfir.assign %[[VAL_6]]#0 to %[[VAL_4]]#0 : !fir.heap>, !fir.ref> +// CHECK: fir.freemem %[[VAL_6]]#0 : !fir.heap> +// CHECK: omp.terminator +// CHECK: } +// CHECK: omp.terminator +// CHECK: } +// CHECK: return +// CHECK: } +func.func @simple(%arg: !fir.ref>) { + omp.parallel { + omp.workshare { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + %ref = hlfir.designate %array#0 (%i) : (!fir.ref>, index) -> !fir.ref + %val = fir.load %ref : !fir.ref + %sub = arith.subi %val, %c1_i32 : i32 + hlfir.yield_element %sub : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + omp.terminator + } + return +} diff --git a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 index 055fdecc9146400226e72bf0a5bd92c998f528c6..dac4938157a60d6739761323b13e7c06807ca93c 100644 --- a/flang/test/Integration/OpenMP/map-types-and-sizes.f90 +++ b/flang/test/Integration/OpenMP/map-types-and-sizes.f90 @@ -30,8 +30,8 @@ subroutine mapType_array !$omp end target end subroutine mapType_array -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [3 x i64] [i64 0, i64 24, i64 4] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [3 x i64] [i64 32, i64 281474976710657, i64 281474976711187] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976711169, i64 281474976711171, i64 281474976711187] subroutine mapType_ptr integer, pointer :: a !$omp target @@ -39,8 +39,8 @@ subroutine mapType_ptr !$omp end target end subroutine mapType_ptr -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [3 x i64] [i64 0, i64 24, i64 4] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [3 x i64] [i64 32, i64 281474976710657, i64 281474976711187] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976711169, i64 281474976711171, i64 281474976711187] subroutine mapType_allocatable integer, allocatable :: a allocate(a) @@ -50,8 +50,8 @@ subroutine mapType_allocatable deallocate(a) end subroutine mapType_allocatable -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [3 x i64] [i64 0, i64 24, i64 4] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [3 x i64] [i64 32, i64 281474976710657, i64 281474976710675] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] subroutine mapType_ptr_explicit integer, pointer :: a !$omp target map(tofrom: a) @@ -59,8 +59,8 @@ subroutine mapType_ptr_explicit !$omp end target end subroutine mapType_ptr_explicit -!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [3 x i64] [i64 0, i64 24, i64 4] -!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [3 x i64] [i64 32, i64 281474976710657, i64 281474976710675] +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] subroutine mapType_allocatable_explicit integer, allocatable :: a allocate(a) @@ -69,7 +69,7 @@ subroutine mapType_allocatable_explicit !$omp end target deallocate(a) end subroutine mapType_allocatable_explicit - + !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 48] !CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 547] subroutine mapType_derived_implicit @@ -78,8 +78,8 @@ subroutine mapType_derived_implicit integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target scalar_arr%int = 1 !$omp end target @@ -93,8 +93,8 @@ subroutine mapType_derived_explicit integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr) scalar_arr%int = 1 !$omp end target @@ -108,8 +108,8 @@ subroutine mapType_derived_explicit_single_member integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%array) scalar_arr%array(1) = 1 !$omp end target @@ -123,8 +123,8 @@ subroutine mapType_derived_explicit_multiple_members integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%int, scalar_arr%real) scalar_arr%int = 1 !$omp end target @@ -138,8 +138,8 @@ subroutine mapType_derived_explicit_member_with_bounds integer(4) :: array(10) integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%array(2:5)) scalar_arr%array(3) = 3 !$omp end target @@ -160,8 +160,8 @@ subroutine mapType_derived_explicit_nested_single_member type(nested) :: nest integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%nest%real) scalar_arr%nest%real = 1 !$omp end target @@ -182,8 +182,8 @@ subroutine mapType_derived_explicit_multiple_nested_members type(nested) :: nest integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%nest%int, scalar_arr%nest%real) scalar_arr%nest%int = 1 !$omp end target @@ -204,13 +204,142 @@ subroutine mapType_derived_explicit_nested_member_with_bounds type(nested) :: nest integer(4) :: int end type scalar_and_array - type(scalar_and_array) :: scalar_arr - + type(scalar_and_array) :: scalar_arr + !$omp target map(tofrom: scalar_arr%nest%array(2:5)) scalar_arr%nest%array(3) = 3 !$omp end target end subroutine mapType_derived_explicit_nested_member_with_bounds +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 48, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] +subroutine mapType_derived_type_alloca() + type :: one_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + end type one_layer + + type(one_layer) :: one_l + + allocate(one_l%array_j(10)) + + !$omp target map(tofrom: one_l%array_j) + one_l%array_j(1) = 10 + !$omp end target +end subroutine + +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [8 x i64] [i64 0, i64 40, i64 8, i64 136, i64 48, i64 8, i64 0, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [8 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710659] +subroutine mapType_alloca_derived_type() + type :: one_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + end type one_layer + + type(one_layer), allocatable :: one_l + + allocate(one_l) + allocate(one_l%array_j(10)) + + !$omp target map(tofrom: one_l%array_j, one_l%k) + one_l%array_j(1) = 10 + one_l%k = 20 + !$omp end target +end subroutine + +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [8 x i64] [i64 0, i64 40, i64 8, i64 240, i64 48, i64 8, i64 0, i64 4] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [8 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710657, i64 281474976710659, i64 281474976710675, i64 281474976710659] +subroutine mapType_alloca_nested_derived_type() + type :: middle_layer + real(4) :: i + integer(4) :: array_i(10) + integer, allocatable :: array_k(:) + integer(4) :: k + end type middle_layer + + type :: top_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + type(middle_layer) :: nest + end type top_layer + + type(top_layer), allocatable :: one_l + + allocate(one_l) + allocate(one_l%nest%array_k(10)) + + !$omp target map(tofrom: one_l%nest%array_k, one_l%nest%k) + one_l%nest%array_k(1) = 10 + one_l%nest%k = 20 + !$omp end target +end subroutine + +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 48, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976710657, i64 281474976710659, i64 281474976710675] +subroutine mapType_nested_derived_type_alloca() + type :: middle_layer + real(4) :: i + integer(4) :: array_i(10) + integer, allocatable :: array_k(:) + integer(4) :: k + end type middle_layer + + type :: top_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + type(middle_layer) :: nest + end type top_layer + + type(top_layer) :: one_l + + allocate(one_l%nest%array_k(10)) + + !$omp target map(tofrom: one_l%nest%array_k) + one_l%nest%array_k(1) = 25 + !$omp end target +end subroutine + +!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [7 x i64] [i64 0, i64 64, i64 8, i64 0, i64 48, i64 8, i64 0] +!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [7 x i64] [i64 32, i64 281474976710657, i64 281474976710656, i64 281474976710672, i64 281474976710657, i64 281474976710659, i64 281474976710675] +subroutine mapType_nested_derived_type_member_idx() +type :: vertexes + integer :: test + integer(4), allocatable :: vertexx(:) + integer(4), allocatable :: vertexy(:) +end type vertexes + +type :: dtype + real(4) :: i + type(vertexes), allocatable :: vertexes(:) + integer(4) :: array_i(10) +end type dtype + +type(dtype) :: alloca_dtype + +allocate(alloca_dtype%vertexes(4)) +allocate(alloca_dtype%vertexes(2)%vertexy(10)) + +!$omp target map(tofrom: alloca_dtype%vertexes(2)%vertexy) + alloca_dtype%vertexes(2)%vertexy(5) = 20 +!$omp end target +end subroutine + !CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [2 x i64] [i64 8, i64 4] !CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [2 x i64] [i64 544, i64 800] subroutine mapType_c_ptr @@ -263,7 +392,7 @@ end subroutine mapType_common_block_members !CHECK: %[[ALLOCA_INT:.*]] = ptrtoint ptr %[[ALLOCA]] to i64 !CHECK: %[[SIZE_DIFF:.*]] = sub i64 %[[ALLOCA_GEP_INT]], %[[ALLOCA_INT]] !CHECK: %[[DIV:.*]] = sdiv exact i64 %[[SIZE_DIFF]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [3 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 0 !CHECK: store i64 %[[DIV]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 !CHECK-LABEL: define {{.*}} @{{.*}}maptype_allocatable_explicit_{{.*}} @@ -273,7 +402,7 @@ end subroutine mapType_common_block_members !CHECK: %[[ALLOCA_INT:.*]] = ptrtoint ptr %[[ALLOCA]] to i64 !CHECK: %[[SIZE_DIFF:.*]] = sub i64 %[[ALLOCA_GEP_INT]], %[[ALLOCA_INT]] !CHECK: %[[DIV:.*]] = sdiv exact i64 %[[SIZE_DIFF]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [3 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 0 !CHECK: store i64 %[[DIV]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 !CHECK-LABEL: define {{.*}} @{{.*}}maptype_derived_implicit_{{.*}} @@ -372,6 +501,294 @@ end subroutine mapType_common_block_members !CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 !CHECK: store ptr %[[ARR_OFF]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK-LABEL: define {{.*}} @{{.*}}maptype_derived_type_alloca_{{.*}} +!CHECK: %[[ALLOCATABLE_DESC_ALLOCA:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8 +!CHECK: %[[ALLOCA:.*]] = alloca %_QFmaptype_derived_type_allocaTone_layer, i64 1, align 8 +!CHECK: %[[DESC_BOUND_ACCESS:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[ALLOCATABLE_DESC_ALLOCA]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[DESC_BOUND_ACCESS_LOAD:.*]] = load i64, ptr %[[DESC_BOUND_ACCESS]], align 8 +!CHECK: %[[OFFSET_UB:.*]] = sub i64 %[[DESC_BOUND_ACCESS_LOAD]], 1 +!CHECK: %[[MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_derived_type_allocaTone_layer, ptr %[[ALLOCA]], i32 0, i32 4 +!CHECK: %[[MEMBER_DESCRIPTOR_BASE_ADDR:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[MEMBER_ACCESS]], i32 0, i32 0 +!CHECK: %[[CALCULATE_DIM_SIZE:.*]] = sub i64 %[[OFFSET_UB]], 0 +!CHECK: %[[RESTORE_OFFSET:.*]] = add i64 %[[CALCULATE_DIM_SIZE]], 1 +!CHECK: %[[MEMBER_BASE_ADDR_SIZE:.*]] = mul i64 1, %[[RESTORE_OFFSET]] +!CHECK: %[[DESC_BASE_ADDR_DATA_SIZE:.*]] = mul i64 %[[MEMBER_BASE_ADDR_SIZE]], 4 +!CHECK: %[[MEMBER_ACCESS_ADDR_END:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[MEMBER_ACCESS]], i64 1 +!CHECK: %[[MEMBER_ACCESS_ADDR_INT:.*]] = ptrtoint ptr %[[MEMBER_ACCESS_ADDR_END]] to i64 +!CHECK: %[[MEMBER_ACCESS_ADDR_BEGIN:.*]] = ptrtoint ptr %[[MEMBER_ACCESS]] to i64 +!CHECK: %[[DTYPE_SEGMENT_SIZE:.*]] = sub i64 %[[MEMBER_ACCESS_ADDR_INT]], %[[MEMBER_ACCESS_ADDR_BEGIN]] +!CHECK: %[[DTYPE_SIZE_CALC:.*]] = sdiv exact i64 %[[DTYPE_SEGMENT_SIZE]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: store ptr %[[ALLOCA]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: store ptr %[[MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: store i64 %[[DTYPE_SIZE_CALC]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: store ptr %[[ALLOCA]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: store ptr %[[MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: store ptr %[[ALLOCA]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[MEMBER_DESCRIPTOR_BASE_ADDR]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[MEMBER_DESCRIPTOR_BASE_ADDR]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: store ptr %array_offset, ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 3 +!CHECK: store i64 %[[DESC_BASE_ADDR_DATA_SIZE]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 + +!CHECK-LABEL: define {{.*}} @{{.*}}maptype_alloca_derived_type_{{.*}} +!CHECK: %{{.*}} = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, align 8 +!CHECK: %[[DTYPE_DESC_ALLOCA:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, align 8 +!CHECK: %[[DTYPE_ARRAY_MEMBER_DESC_ALLOCA:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8 +!CHECK: %[[DTYPE_DESC_ALLOCA_2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, align 8 +!CHECK: %[[DTYPE_DESC_ALLOCA_3:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1, align 8 +!CHECK: %[[ACCESS_DESC_MEMBER_UB:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[DTYPE_ARRAY_MEMBER_DESC_ALLOCA]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[LOAD_DESC_MEMBER_UB:.*]] = load i64, ptr %[[ACCESS_DESC_MEMBER_UB]], align 8 +!CHECK: %[[OFFSET_MEMBER_UB:.*]] = sub i64 %[[LOAD_DESC_MEMBER_UB]], 1 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_2]], i32 0, i32 0 +!CHECK: %[[DTYPE_BASE_ADDR_LOAD:.*]] = load ptr, ptr %[[DTYPE_BASE_ADDR_ACCESS]], align 8 +!CHECK: %[[DTYPE_ALLOCA_MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_alloca_derived_typeTone_layer, ptr %[[DTYPE_BASE_ADDR_LOAD]], i32 0, i32 4 +!CHECK: %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[DTYPE_ALLOCA_MEMBER_ACCESS]], i32 0, i32 0 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA]], i32 0, i32 0 +!CHECK: %[[DTYPE_BASE_ADDR_LOAD_2:.*]] = load ptr, ptr %[[DTYPE_BASE_ADDR_ACCESS_2]], align 8 +!CHECK: %[[DTYPE_NONALLOCA_MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_alloca_derived_typeTone_layer, ptr %[[DTYPE_BASE_ADDR_LOAD_2]], i32 0, i32 5 +!CHECK: %[[DTYPE_BASE_ADDR_ACCESS_3:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 0, i32 0 +!CHECK: %[[MEMBER_SIZE_CALC_1:.*]] = sub i64 %[[OFFSET_MEMBER_UB]], 0 +!CHECK: %[[MEMBER_SIZE_CALC_2:.*]] = add i64 %[[MEMBER_SIZE_CALC_1]], 1 +!CHECK: %[[MEMBER_SIZE_CALC_3:.*]] = mul i64 1, %[[MEMBER_SIZE_CALC_2]] +!CHECK: %[[MEMBER_SIZE_CALC_4:.*]] = mul i64 %[[MEMBER_SIZE_CALC_3]], 4 +!CHECK: %[[DTYPE_BASE_ADDR_LOAD_3:.*]] = load ptr, ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], align 8 +!CHECK: %[[LOAD_DTYPE_DESC_MEMBER:.*]] = load ptr, ptr %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS]], align 8 +!CHECK: %[[MEMBER_ARRAY_OFFSET:.*]] = getelementptr inbounds i32, ptr %[[LOAD_DTYPE_DESC_MEMBER]], i64 0 +!CHECK: %[[DTYPE_END_OFFSET:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 1 +!CHECK: %[[DTYPE_END:.*]] = ptrtoint ptr %[[DTYPE_END_OFFSET]] to i64 +!CHECK: %[[DTYPE_BEGIN:.*]] = ptrtoint ptr %[[DTYPE_DESC_ALLOCA_3]] to i64 +!CHECK: %[[DTYPE_DESC_SZ_CALC:.*]] = sub i64 %[[DTYPE_END]], %[[DTYPE_BEGIN]] +!CHECK: %[[DTYPE_DESC_SZ:.*]] = sdiv exact i64 %[[DTYPE_DESC_SZ_CALC]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: store i64 %[[DTYPE_DESC_SZ]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[DTYPE_BASE_ADDR_ACCESS_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: store ptr %[[DTYPE_BASE_ADDR_LOAD_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 4 +!CHECK: store ptr %[[DTYPE_ALLOCA_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 5 +!CHECK: store ptr %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 +!CHECK: store ptr %[[DTYPE_ALLOCA_MEMBER_BASE_ADDR_ACCESS]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 6 +!CHECK: store ptr %[[MEMBER_ARRAY_OFFSET]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 6 +!CHECK: store i64 %[[MEMBER_SIZE_CALC_4]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 7 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 7 +!CHECK: store ptr %[[DTYPE_NONALLOCA_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 + +!CHECK-LABEL: define {{.*}} @{{.*}}maptype_alloca_nested_derived_type{{.*}} +!CHECK: %{{.*}} = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, align 8 +!CHECK: %[[DTYPE_DESC_ALLOCA_1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, align 8 +!CHECK: %[[ALLOCATABLE_MEMBER_ALLOCA:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8 +!CHECK: %[[DTYPE_DESC_ALLOCA_2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, align 8 +!CHECK: %[[DTYPE_DESC_ALLOCA_3:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1, align 8 +!CHECK: %[[ALLOCATABLE_MEMBER_ALLOCA_UB:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[ALLOCATABLE_MEMBER_ALLOCA]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[ALLOCATABLE_MEMBER_ALLOCA_UB_LOAD:.*]] = load i64, ptr %[[ALLOCATABLE_MEMBER_ALLOCA_UB]], align 8 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_1:.*]] = sub i64 %[[ALLOCATABLE_MEMBER_ALLOCA_UB_LOAD]], 1 +!CHECK: %[[DTYPE_DESC_BASE_ADDR_ACCESS:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_2]], i32 0, i32 0 +!CHECK: %[[DTYPE_DESC_BASE_ADDR_LOAD:.*]] = load ptr, ptr %[[DTYPE_DESC_BASE_ADDR_ACCESS]], align 8 +!CHECK: %[[NESTED_DTYPE_ACCESS:.*]] = getelementptr %_QFmaptype_alloca_nested_derived_typeTtop_layer, ptr %[[DTYPE_DESC_BASE_ADDR_LOAD]], i32 0, i32 6 +!CHECK: %[[MAPPED_MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_alloca_nested_derived_typeTmiddle_layer, ptr %[[NESTED_DTYPE_ACCESS]], i32 0, i32 2 +!CHECK: %[[MAPPED_MEMBER_BASE_ADDR_ACCESS:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[MAPPED_MEMBER_ACCESS]], i32 0, i32 0 +!CHECK: %[[DTYPE_DESC_BASE_ADDR_ACCESS_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_1]], i32 0, i32 0 +!CHECK: %[[DTYPE_DESC_BASE_ADDR_LOAD_2:.*]] = load ptr, ptr %[[DTYPE_DESC_BASE_ADDR_ACCESS_2]], align 8 +!CHECK: %[[NESTED_DTYPE_ACCESS:.*]] = getelementptr %_QFmaptype_alloca_nested_derived_typeTtop_layer, ptr %[[DTYPE_DESC_BASE_ADDR_LOAD_2]], i32 0, i32 6 +!CHECK: %[[NESTED_NONALLOCA_MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_alloca_nested_derived_typeTmiddle_layer, ptr %[[NESTED_DTYPE_ACCESS]], i32 0, i32 3 +!CHECK: %[[DTYPE_DESC_BASE_ADDR:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 0, i32 0 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_2:.*]] = sub i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_1]], 0 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_3:.*]] = add i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_2]], 1 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_4:.*]] = mul i64 1, %[[ALLOCATABLE_MEMBER_SIZE_CALC_3]] +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_5:.*]] = mul i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_4]], 4 +!CHECK: %[[LOAD_BASE_ADDR:.*]] = load ptr, ptr %[[DTYPE_DESC_BASE_ADDR]], align 8 +!CHECK: %[[LOAD_DESC_MEMBER_BASE_ADDR:.*]] = load ptr, ptr %[[MAPPED_MEMBER_BASE_ADDR_ACCESS]], align 8 +!CHECK: %[[ARRAY_OFFSET:.*]] = getelementptr inbounds i32, ptr %[[LOAD_DESC_MEMBER_BASE_ADDR]], i64 0 +!CHECK: %[[DTYPE_DESC_SIZE_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[DTYPE_DESC_ALLOCA_3]], i32 1 +!CHECK: %[[DTYPE_DESC_SIZE_CALC_2:.*]] = ptrtoint ptr %[[DTYPE_DESC_SIZE_CALC_1]] to i64 +!CHECK: %[[DTYPE_DESC_SIZE_CALC_3:.*]] = ptrtoint ptr %[[DTYPE_DESC_ALLOCA_3]] to i64 +!CHECK: %[[DTYPE_DESC_SIZE_CALC_4:.*]] = sub i64 %[[DTYPE_DESC_SIZE_CALC_2]], %[[DTYPE_DESC_SIZE_CALC_3]] +!CHECK: %[[DTYPE_DESC_SIZE_CALC_5:.*]] = sdiv exact i64 %[[DTYPE_DESC_SIZE_CALC_4]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: store i64 %[[DTYPE_DESC_SIZE_CALC_5]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[DTYPE_DESC_BASE_ADDR]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[DTYPE_DESC_BASE_ADDR]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: store ptr %[[LOAD_BASE_ADDR]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 4 +!CHECK: store ptr %[[MAPPED_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 5 +!CHECK: store ptr %[[MAPPED_MEMBER_BASE_ADDR_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 +!CHECK: store ptr %[[MAPPED_MEMBER_BASE_ADDR_ACCESS]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 6 +!CHECK: store ptr %[[ARRAY_OFFSET]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [8 x i64], ptr %.offload_sizes, i32 0, i32 6 +!CHECK: store i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_5]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_baseptrs, i32 0, i32 7 +!CHECK: store ptr %[[DTYPE_DESC_ALLOCA_3]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [8 x ptr], ptr %.offload_ptrs, i32 0, i32 7 +!CHECK: store ptr %[[NESTED_NONALLOCA_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 + +!CHECK-LABEL: define {{.*}} @{{.*}}maptype_nested_derived_type_alloca{{.*}} +!CHECK: %[[ALLOCATABLE_MEMBER_ALLOCA:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8 +!CHECK: %[[ALLOCA:.*]] = alloca %_QFmaptype_nested_derived_type_allocaTtop_layer, i64 1, align 8 +!CHECK: %[[ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[ALLOCATABLE_MEMBER_ALLOCA]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[ALLOCATABLE_MEMBER_ADDR_LOAD:.*]] = load i64, ptr %[[ALLOCATABLE_MEMBER_BASE_ADDR]], align 8 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_1:.*]] = sub i64 %[[ALLOCATABLE_MEMBER_ADDR_LOAD]], 1 +!CHECK: %[[NESTED_DTYPE_MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_nested_derived_type_allocaTtop_layer, ptr %[[ALLOCA]], i32 0, i32 6 +!CHECK: %[[NESTED_MEMBER_ACCESS:.*]] = getelementptr %_QFmaptype_nested_derived_type_allocaTmiddle_layer, ptr %[[NESTED_DTYPE_MEMBER_ACCESS]], i32 0, i32 2 +!CHECK: %[[NESTED_MEMBER_BASE_ADDR_ACCESS:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %{{.*}}, i32 0, i32 0 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_2:.*]] = sub i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_1]], 0 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_3:.*]] = add i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_2]], 1 +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_4:.*]] = mul i64 1, %[[ALLOCATABLE_MEMBER_SIZE_CALC_3]] +!CHECK: %[[ALLOCATABLE_MEMBER_SIZE_CALC_5:.*]] = mul i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_4]], 4 +!CHECK: %[[LOAD_BASE_ADDR:.*]] = load ptr, ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS]], align 8 +!CHECK: %[[ARR_OFFS:.*]] = getelementptr inbounds i32, ptr %[[LOAD_BASE_ADDR]], i64 0 +!CHECK: %[[NESTED_MEMBER_BASE_ADDR_ACCESS_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[NESTED_MEMBER_ACCESS]], i64 1 +!CHECK: %[[DTYPE_SEGMENT_SIZE_CALC_1:.*]] = ptrtoint ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS_2]] to i64 +!CHECK: %[[DTYPE_SEGMENT_SIZE_CALC_2:.*]] = ptrtoint ptr %[[NESTED_MEMBER_ACCESS]] to i64 +!CHECK: %[[DTYPE_SEGMENT_SIZE_CALC_3:.*]] = sub i64 %[[DTYPE_SEGMENT_SIZE_CALC_1]], %[[DTYPE_SEGMENT_SIZE_CALC_2]] +!CHECK: %[[DTYPE_SEGMENT_SIZE_CALC_4:.*]] = sdiv exact i64 %[[DTYPE_SEGMENT_SIZE_CALC_3]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: store ptr %[[ALLOCA]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: store ptr %[[NESTED_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: store i64 %[[DTYPE_SEGMENT_SIZE_CALC_4]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: store ptr %[[ALLOCA]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: store ptr %[[NESTED_MEMBER_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: store ptr %[[ALLOCA]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[NESTED_MEMBER_BASE_ADDR_ACCESS]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [4 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: store ptr %[[ARR_OFFS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [4 x i64], ptr %.offload_sizes, i32 0, i32 3 +!CHECK: store i64 %[[ALLOCATABLE_MEMBER_SIZE_CALC_5]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 + +!CHECK-LABEL: define {{.*}} @{{.*}}maptype_nested_derived_type_member_idx{{.*}} +!CHECK: %[[ALLOCA_0:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, align 8 +!CHECK: %[[ALLOCA_1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, align 8 +!CHECK: %[[ALLOCA:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, align 8 +!CHECK: %[[BASE_PTR_1:.*]] = alloca %_QFmaptype_nested_derived_type_member_idxTdtype, i64 1, align 8 +!CHECK: %{{.*}} = getelementptr %_QFmaptype_nested_derived_type_member_idxTdtype, ptr %[[BASE_PTR_1]], i32 0, i32 1 +!CHECK: %[[BOUNDS_ACC:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[BOUNDS_LD:.*]] = load i64, ptr %[[BOUNDS_ACC]], align 8 +!CHECK: %[[BOUNDS_ACC_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[ALLOCA_1]], i32 0, i32 7, i64 0, i32 1 +!CHECK: %[[BOUNDS_LD_2:.*]] = load i64, ptr %[[BOUNDS_ACC_2]], align 8 +!CHECK: %[[BOUNDS_CALC:.*]] = sub i64 %[[BOUNDS_LD_2]], 1 +!CHECK: %[[OFF_PTR_1:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTdtype, ptr %[[BASE_PTR_1]], i32 0, i32 1 +!CHECK: %[[OFF_PTR_CALC_0:.*]] = sub i64 %[[BOUNDS_LD]], 1 +!CHECK: %[[OFF_PTR_2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[OFF_PTR_1]], i32 0, i32 0 +!CHECK: %[[GEP_DESC_PTR:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 0 +!CHECK: %[[LOAD_DESC_PTR:.*]] = load ptr, ptr %[[GEP_DESC_PTR]], align 8 +!CHECK: %[[SZ_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[ALLOCA_0]], i32 0, i32 7, i32 0, i32 2 +!CHECK: %[[SZ_CALC_2:.*]] = load i64, ptr %[[SZ_CALC_1]], align 8 +!CHECK: %[[SZ_CALC_3:.*]] = mul nsw i64 1, %[[SZ_CALC_2]] +!CHECK: %[[SZ_CALC_4:.*]] = add nsw i64 %[[SZ_CALC_3]], 0 +!CHECK: %[[SZ_CALC_5:.*]] = getelementptr i8, ptr %[[LOAD_DESC_PTR]], i64 %[[SZ_CALC_4]] +!CHECK: %[[SZ_CALC_6:.*]] = getelementptr %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[SZ_CALC_5]], i32 0, i32 2 +!CHECK: %[[OFF_PTR_4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[SZ_CALC_6]], i32 0, i32 0 +!CHECK: %[[OFF_PTR_CALC_1:.*]] = sub i64 %[[OFF_PTR_CALC_0]], 0 +!CHECK: %[[OFF_PTR_CALC_2:.*]] = add i64 %[[OFF_PTR_CALC_1]], 1 +!CHECK: %[[OFF_PTR_CALC_3:.*]] = mul i64 1, %[[OFF_PTR_CALC_2]] +!CHECK: %[[OFF_PTR_3:.*]] = mul i64 %[[OFF_PTR_CALC_3]], 104 +!CHECK: %[[SZ_CALC_1_2:.*]] = sub i64 %[[BOUNDS_CALC]], 0 +!CHECK: %[[SZ_CALC_2_2:.*]] = add i64 %[[SZ_CALC_1_2]], 1 +!CHECK: %[[SZ_CALC_3_2:.*]] = mul i64 1, %[[SZ_CALC_2_2]] +!CHECK: %[[SZ_CALC_4_2:.*]] = mul i64 %[[SZ_CALC_3_2]], 4 +!CHECK: %[[LOAD_OFF_PTR:.*]] = load ptr, ptr %[[OFF_PTR_2]], align 8 +!CHECK: %[[ARR_OFFS:.*]] = getelementptr inbounds %_QFmaptype_nested_derived_type_member_idxTvertexes, ptr %[[LOAD_OFF_PTR]], i64 0 +!CHECK: %[[LOAD_ARR_OFFS:.*]] = load ptr, ptr %[[OFF_PTR_4]], align 8 +!CHECK: %[[ARR_OFFS_1:.*]] = getelementptr inbounds i32, ptr %[[LOAD_ARR_OFFS]], i64 0 +!CHECK: %[[SZ_CALC_1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[OFF_PTR_1]], i64 1 +!CHECK: %[[SZ_CALC_2:.*]] = ptrtoint ptr %[[SZ_CALC_1]] to i64 +!CHECK: %[[SZ_CALC_3:.*]] = ptrtoint ptr %[[OFF_PTR_1]] to i64 +!CHECK: %[[SZ_CALC_4:.*]] = sub i64 %[[SZ_CALC_2]], %[[SZ_CALC_3]] +!CHECK: %[[SZ_CALC_5:.*]] = sdiv exact i64 %[[SZ_CALC_4]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +!CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +!CHECK: store ptr %[[OFF_PTR_1]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [7 x i64], ptr %.offload_sizes, i32 0, i32 0 +!CHECK: store i64 %[[SZ_CALC_5]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 1 +!CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 1 +!CHECK: store ptr %[[OFF_PTR_1]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 2 +!CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 2 +!CHECK: store ptr %[[OFF_PTR_2]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 3 +!CHECK: store ptr %[[OFF_PTR_2]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 3 +!CHECK: store ptr %[[ARR_OFFS]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [7 x i64], ptr %.offload_sizes, i32 0, i32 3 +!CHECK: store i64 %[[OFF_PTR_3]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 4 +!CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 4 +!CHECK: store ptr %[[SZ_CALC_6]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 5 +!CHECK: store ptr %[[BASE_PTR_1]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 5 +!CHECK: store ptr %[[OFF_PTR_4]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_baseptrs, i32 0, i32 6 +!CHECK: store ptr %[[OFF_PTR_4]], ptr %[[BASE_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_PTR_ARR:.*]] = getelementptr inbounds [7 x ptr], ptr %.offload_ptrs, i32 0, i32 6 +!CHECK: store ptr %[[ARR_OFFS_1]], ptr %[[OFFLOAD_PTR_ARR]], align 8 +!CHECK: %[[OFFLOAD_SIZE_ARR:.*]] = getelementptr inbounds [7 x i64], ptr %.offload_sizes, i32 0, i32 6 +!CHECK: store i64 %[[SZ_CALC_4_2]], ptr %[[OFFLOAD_SIZE_ARR]], align 8 + !CHECK-LABEL: define {{.*}} @{{.*}}maptype_common_block_{{.*}} !CHECK: %[[BASE_PTR_ARR:.*]] = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 !CHECK: store ptr @var_common_, ptr %[[BASE_PTR_ARR]], align 8 diff --git a/flang/test/Integration/OpenMP/workshare-array-array-assign.f90 b/flang/test/Integration/OpenMP/workshare-array-array-assign.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e9ec5d9175beb5935f38f788135501bcebd9c36e --- /dev/null +++ b/flang/test/Integration/OpenMP/workshare-array-array-assign.f90 @@ -0,0 +1,34 @@ +!===----------------------------------------------------------------------===! +! This directory can be used to add Integration tests involving multiple +! stages of the compiler (for eg. from Fortran to LLVM IR). It should not +! contain executable tests. We should only add tests here sparingly and only +! if there is no other way to test. Repeat this message in each test that is +! added to this directory and sub-directories. +!===----------------------------------------------------------------------===! + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix HLFIR +!RUN: %flang_fc1 -emit-fir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix FIR + +subroutine sb1(x, y) + integer :: x(:) + integer :: y(:) + !$omp parallel workshare + x = y + !$omp end parallel workshare +end subroutine + +! HLFIR: omp.parallel { +! HLFIR: omp.workshare { +! HLFIR: hlfir.assign +! HLFIR: omp.terminator +! HLFIR: } +! HLFIR: omp.terminator +! HLFIR: } + +! FIR: omp.parallel { +! FIR: omp.wsloop nowait { +! FIR: omp.loop_nest +! FIR: } +! FIR: omp.barrier +! FIR: omp.terminator +! FIR: } diff --git a/flang/test/Integration/OpenMP/workshare-axpy.f90 b/flang/test/Integration/OpenMP/workshare-axpy.f90 new file mode 100644 index 0000000000000000000000000000000000000000..0c4524f8552906d54007d220cf22dfca01df0984 --- /dev/null +++ b/flang/test/Integration/OpenMP/workshare-axpy.f90 @@ -0,0 +1,57 @@ +!===----------------------------------------------------------------------===! +! This directory can be used to add Integration tests involving multiple +! stages of the compiler (for eg. from Fortran to LLVM IR). It should not +! contain executable tests. We should only add tests here sparingly and only +! if there is no other way to test. Repeat this message in each test that is +! added to this directory and sub-directories. +!===----------------------------------------------------------------------===! + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix HLFIR +!RUN: %flang_fc1 -emit-fir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix FIR + +subroutine sb1(a, x, y, z) + integer :: a + integer :: x(:) + integer :: y(:) + integer :: z(:) + !$omp parallel workshare + z = a * x + y + !$omp end parallel workshare +end subroutine + +! HLFIR: func.func @_QPsb1 +! HLFIR: omp.parallel { +! HLFIR: omp.workshare { +! HLFIR: hlfir.elemental {{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! HLFIR: hlfir.elemental {{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr { +! HLFIR: hlfir.assign +! HLFIR: hlfir.destroy +! HLFIR: hlfir.destroy +! HLFIR-NOT: omp.barrier +! HLFIR: omp.terminator +! HLFIR: } +! HLFIR-NOT: omp.barrier +! HLFIR: omp.terminator +! HLFIR: } +! HLFIR: return +! HLFIR: } +! HLFIR:} + + +! FIR: func.func private @_workshare_copy_heap_Uxi32(%{{[a-z0-9]+}}: !fir.ref>>, %{{[a-z0-9]+}}: !fir.ref>> +! FIR: func.func private @_workshare_copy_i32(%{{[a-z0-9]+}}: !fir.ref, %{{[a-z0-9]+}}: !fir.ref + +! FIR: func.func @_QPsb1 +! FIR: omp.parallel { +! FIR: omp.single copyprivate(%9 -> @_workshare_copy_i32 : !fir.ref, %10 -> @_workshare_copy_heap_Uxi32 : !fir.ref>>) { +! FIR: fir.allocmem +! FIR: omp.wsloop { +! FIR: omp.loop_nest +! FIR: omp.single nowait { +! FIR: fir.call @_FortranAAssign +! FIR: fir.freemem +! FIR: omp.terminator +! FIR: } +! FIR: omp.barrier +! FIR: omp.terminator +! FIR: } diff --git a/flang/test/Integration/OpenMP/workshare-scalar-array-assign.f90 b/flang/test/Integration/OpenMP/workshare-scalar-array-assign.f90 new file mode 100644 index 0000000000000000000000000000000000000000..6c180cd639997c0b23af22bde03549daac401b48 --- /dev/null +++ b/flang/test/Integration/OpenMP/workshare-scalar-array-assign.f90 @@ -0,0 +1,45 @@ +!===----------------------------------------------------------------------===! +! This directory can be used to add Integration tests involving multiple +! stages of the compiler (for eg. from Fortran to LLVM IR). It should not +! contain executable tests. We should only add tests here sparingly and only +! if there is no other way to test. Repeat this message in each test that is +! added to this directory and sub-directories. +!===----------------------------------------------------------------------===! + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix HLFIR +!RUN: %flang_fc1 -emit-fir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix FIR + +subroutine sb1(a, x) + integer :: a + integer :: x(:) + !$omp parallel workshare + x = a + !$omp end parallel workshare +end subroutine + +! HLFIR: omp.parallel { +! HLFIR: omp.workshare { +! HLFIR: %[[SCALAR:.*]] = fir.load %1#0 : !fir.ref +! HLFIR: hlfir.assign %[[SCALAR]] to +! HLFIR: omp.terminator +! HLFIR: } +! HLFIR: omp.terminator +! HLFIR: } + +! FIR: omp.parallel { +! FIR: %[[SCALAR_ALLOCA:.*]] = fir.alloca i32 +! FIR: omp.single copyprivate(%[[SCALAR_ALLOCA]] -> @_workshare_copy_i32 : !fir.ref) { +! FIR: %[[SCALAR_LOAD:.*]] = fir.load %{{.*}} : !fir.ref +! FIR: fir.store %[[SCALAR_LOAD]] to %[[SCALAR_ALLOCA]] : !fir.ref +! FIR: omp.terminator +! FIR: } +! FIR: %[[SCALAR_RELOAD:.*]] = fir.load %[[SCALAR_ALLOCA]] : !fir.ref +! FIR: %6:3 = fir.box_dims %3, %c0 : (!fir.box>, index) -> (index, index, index) +! FIR: omp.wsloop nowait { +! FIR: omp.loop_nest (%arg2) : index = (%c1) to (%6#1) inclusive step (%c1) { +! FIR: fir.store %[[SCALAR_RELOAD]] +! FIR: omp.yield +! FIR: } +! FIR: } +! FIR: omp.barrier +! FIR: omp.terminator diff --git a/flang/test/Integration/OpenMP/workshare-scalar-array-mul.f90 b/flang/test/Integration/OpenMP/workshare-scalar-array-mul.f90 new file mode 100644 index 0000000000000000000000000000000000000000..9b8ef66b48f47df2ac1d5195063d585eca14fa9e --- /dev/null +++ b/flang/test/Integration/OpenMP/workshare-scalar-array-mul.f90 @@ -0,0 +1,65 @@ +!===----------------------------------------------------------------------===! +! This directory can be used to add Integration tests involving multiple +! stages of the compiler (for eg. from Fortran to LLVM IR). It should not +! contain executable tests. We should only add tests here sparingly and only +! if there is no other way to test. Repeat this message in each test that is +! added to this directory and sub-directories. +!===----------------------------------------------------------------------===! + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix HLFIR-O3 +!RUN: %flang_fc1 -emit-fir -fopenmp -O3 %s -o - | FileCheck %s --check-prefix FIR-O3 + +!RUN: %flang_fc1 -emit-hlfir -fopenmp -O0 %s -o - | FileCheck %s --check-prefix HLFIR-O0 +!RUN: %flang_fc1 -emit-fir -fopenmp -O0 %s -o - | FileCheck %s --check-prefix FIR-O0 + +program test + real :: arr_01(10) + !$omp parallel workshare + arr_01 = arr_01*2 + !$omp end parallel workshare +end program + +! HLFIR-O3: omp.parallel { +! HLFIR-O3: omp.workshare { +! HLFIR-O3: hlfir.elemental +! HLFIR-O3: hlfir.assign +! HLFIR-O3: hlfir.destroy +! HLFIR-O3: omp.terminator +! HLFIR-O3: omp.terminator + +! FIR-O3: omp.parallel { +! FIR-O3: omp.wsloop nowait { +! FIR-O3: omp.loop_nest +! FIR-O3: omp.barrier +! FIR-O3: omp.terminator + +! HLFIR-O0: omp.parallel { +! HLFIR-O0: omp.workshare { +! HLFIR-O0: hlfir.elemental +! HLFIR-O0: hlfir.assign +! HLFIR-O0: hlfir.destroy +! HLFIR-O0: omp.terminator +! HLFIR-O0: omp.terminator + +! Check the copyprivate copy function +! FIR-O0: func.func private @_workshare_copy_heap_{{.*}}(%[[DST:.*]]: {{.*}}, %[[SRC:.*]]: {{.*}}) +! FIR-O0: fir.load %[[SRC]] +! FIR-O0: fir.store {{.*}} to %[[DST]] + +! Check that we properly handle the temporary array +! FIR-O0: omp.parallel { +! FIR-O0: %[[CP:.*]] = fir.alloca !fir.heap> +! FIR-O0: omp.single copyprivate(%[[CP]] -> @_workshare_copy_heap_ +! FIR-O0: fir.allocmem +! FIR-O0: fir.store +! FIR-O0: omp.terminator +! FIR-O0: fir.load %[[CP]] +! FIR-O0: omp.wsloop { +! FIR-O0: omp.loop_nest +! FIR-O0: omp.yield +! FIR-O0: omp.single nowait { +! FIR-O0: fir.call @_FortranAAssign +! FIR-O0: fir.freemem +! FIR-O0: omp.terminator +! FIR-O0: omp.barrier +! FIR-O0: omp.terminator diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf index 2f76b5e78800adac825b0a6d6c3d9a0e5f034ec0..3b6cd67d9a8fa5f6258dbba3eb99a06116e45123 100644 --- a/flang/test/Lower/CUDA/cuda-data-transfer.cuf +++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf @@ -7,6 +7,8 @@ module mod1 integer :: i end type + integer, device, dimension(11:20) :: cdev + contains function dev1(a) integer, device :: a(:) @@ -16,6 +18,7 @@ contains end subroutine sub1() + use mod1 integer, device :: m integer, device :: adev(10) integer :: i, ahost(10), bhost(10) @@ -34,6 +37,8 @@ subroutine sub1() adev = 10 + cdev = 0 + end ! CHECK-LABEL: func.func @_QPsub1() @@ -70,6 +75,8 @@ end ! CHECK: cuf.data_transfer %c10{{.*}} to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer} : i32, !fir.ref> +! CHECK: cuf.data_transfer %c0{{.*}} to %{{.*}}#1, %{{.*}} : !fir.shapeshift<1> {transfer_kind = #cuf.cuda_transfer} : i32, !fir.ref> + subroutine sub2() integer, device :: m integer, device :: adev(10), bdev(10) @@ -124,7 +131,7 @@ end ! CHECK: %[[TMP:.*]] = fir.alloca !fir.type<_QMmod1Tt1{i:i32}> {bindc_name = ".tmp"} ! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub3Eahost"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[BHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub3Ebhost"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) -! CHECK: %[[T:.*]]:2 = hlfir.declare %7 {data_attr = #cuf.cuda, uniq_name = "_QFsub3Et"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[T:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda, uniq_name = "_QFsub3Et"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[TMP_DECL:.*]]:2 = hlfir.declare %0 {uniq_name = ".tmp"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: cuf.data_transfer %[[T]]#1 to %[[TMP_DECL]]#0 {transfer_kind = #cuf.cuda_transfer} : !fir.ref>, !fir.ref> diff --git a/flang/test/Lower/CUDA/cuda-return01.cuf b/flang/test/Lower/CUDA/cuda-return01.cuf new file mode 100644 index 0000000000000000000000000000000000000000..c9f9a8b57ef0416fbfad648275c63cac36f322c7 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-return01.cuf @@ -0,0 +1,14 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +! Check if finalization works with a return statement + +program main + integer, device :: a(10) + return +end + +! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK: %[[DECL:.*]]:2 = hlfir.declare +! CHECK-NEXT: cuf.free %[[DECL]]#1 : !fir.ref> +! CHECK-NEXT: return +! CHECK-NEXT: } diff --git a/flang/test/Lower/CUDA/cuda-return02.cuf b/flang/test/Lower/CUDA/cuda-return02.cuf new file mode 100644 index 0000000000000000000000000000000000000000..5d01f0a24b420b72c9a73d895d5a5f12eb1ed3a0 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-return02.cuf @@ -0,0 +1,48 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +! Check if finalization works with multiple return statements + +program test + integer, device :: a(10) + logical :: l + + if (l) then + return + end if + + return +end + +! CHECK: func.func @_QQmain() attributes {fir.bindc_name = "test"} { +! CHECK: %[[DECL:.*]]:2 = hlfir.declare +! CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2 +! CHECK-NEXT: ^bb1: +! CHECK-NEXT: cuf.free %[[DECL]]#1 : !fir.ref> +! CHECK-NEXT: return +! CHECK-NEXT: ^bb2: +! CHECK-NEXT: cuf.free %[[DECL]]#1 : !fir.ref> +! CHECK-NEXT: return +! CHECK-NEXT: } + +subroutine sub(l) + integer, device :: a(10) + logical :: l + + if (l) then + l = .false. + return + end if + + return +end + +! CHECK: func.func @_QPsub(%arg0: !fir.ref> {fir.bindc_name = "l"}) { +! CHECK: %[[DECL:.*]]:2 = hlfir.declare +! CHECK: cf.cond_br %6, ^bb1, ^bb2 +! CHECK: ^bb1: +! CHECK: cf.br ^bb3 +! CHECK: ^bb2: +! CHECK: cf.br ^bb3 +! CHECK: ^bb3: +! CHECK: cuf.free %[[DECL]]#1 : !fir.ref> +! CHECK: } diff --git a/flang/test/Lower/HLFIR/maxloc.f90 b/flang/test/Lower/HLFIR/maxloc.f90 index 166a1b9db1724ebbcb7a1c5bb883c336bda061f1..539affad2d7df11d4ccbbf89f2195624e793b93a 100644 --- a/flang/test/Lower/HLFIR/maxloc.f90 +++ b/flang/test/Lower/HLFIR/maxloc.f90 @@ -341,8 +341,8 @@ end subroutine test_unknown_char_len_result ! CHECK-DAG: %[[C1_7:.*]] = arith.constant 1 : index ! CHECK-DAG: %[[C3_8:.*]] = arith.constant 3 : index ! CHECK-DAG: %[[C3_9:.*]] = arith.constant 3 : index -! CHECK-DAG: %[[ARRAY_BOX:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] -! CHECK: %[[EXPR:.*]] = hlfir.maxloc %[[ARRAY_BOX]] {fastmath = #arith.fastmath} : (!fir.box>>) -> !hlfir.expr<2xi32> +! CHECK-DAG: %[[ARRAY_REF:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] : (!fir.ref>>, index, index, index, index, index, index, index, index, !fir.shape<2>, index) -> !fir.ref>> +! CHECK: %[[EXPR:.*]] = hlfir.maxloc %[[ARRAY_REF]] {fastmath = #arith.fastmath} : (!fir.ref>>) -> !hlfir.expr<2xi32> ! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[RES]]#0 : !hlfir.expr<2xi32>, !fir.ref> ! CHECK-NEXT: hlfir.destroy %[[EXPR]] ! CHECK-NEXT: return diff --git a/flang/test/Lower/HLFIR/maxval.f90 b/flang/test/Lower/HLFIR/maxval.f90 index 5adad286a77d28bac9df84671b9dfb91e231bc09..32e1a80417a27b7cdb0798135934d783005e74db 100644 --- a/flang/test/Lower/HLFIR/maxval.f90 +++ b/flang/test/Lower/HLFIR/maxval.f90 @@ -254,8 +254,8 @@ end subroutine test_unknown_char_len_result ! CHECK-DAG: %[[C1_7:.*]] = arith.constant 1 : index ! CHECK-DAG: %[[C3_8:.*]] = arith.constant 3 : index ! CHECK-DAG: %[[C3_9:.*]] = arith.constant 3 : index -! CHECK-DAG: %[[ARRAY_BOX:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] -! CHECK: %[[EXPR:.*]] = hlfir.maxval %[[ARRAY_BOX]] {fastmath = #arith.fastmath} : (!fir.box>>) -> !hlfir.expr> +! CHECK-DAG: %[[ARRAY_REF:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] : (!fir.ref>>, index, index, index, index, index, index, index, index, !fir.shape<2>, index) -> !fir.ref>> +! CHECK: %[[EXPR:.*]] = hlfir.maxval %[[ARRAY_REF]] {fastmath = #arith.fastmath} : (!fir.ref>>) -> !hlfir.expr> ! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[RES]]#0 : !hlfir.expr>, !fir.ref> ! CHECK-NEXT: hlfir.destroy %[[EXPR]] ! CHECK-NEXT: return diff --git a/flang/test/Lower/HLFIR/minloc.f90 b/flang/test/Lower/HLFIR/minloc.f90 index f835cf54b2a73e428ed448c3ffa521b5c343c17a..ce149ffcfb54fd5877f44782613ea7d8e0380bb5 100644 --- a/flang/test/Lower/HLFIR/minloc.f90 +++ b/flang/test/Lower/HLFIR/minloc.f90 @@ -341,8 +341,8 @@ end subroutine test_unknown_char_len_result ! CHECK-DAG: %[[C1_7:.*]] = arith.constant 1 : index ! CHECK-DAG: %[[C3_8:.*]] = arith.constant 3 : index ! CHECK-DAG: %[[C3_9:.*]] = arith.constant 3 : index -! CHECK-DAG: %[[ARRAY_BOX:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] -! CHECK: %[[EXPR:.*]] = hlfir.minloc %[[ARRAY_BOX]] {fastmath = #arith.fastmath} : (!fir.box>>) -> !hlfir.expr<2xi32> +! CHECK-DAG: %[[ARRAY_REF:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] : (!fir.ref>>, index, index, index, index, index, index, index, index, !fir.shape<2>, index) -> !fir.ref>> +! CHECK: %[[EXPR:.*]] = hlfir.minloc %[[ARRAY_REF]] {fastmath = #arith.fastmath} : (!fir.ref>>) -> !hlfir.expr<2xi32> ! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[RES]]#0 : !hlfir.expr<2xi32>, !fir.ref> ! CHECK-NEXT: hlfir.destroy %[[EXPR]] ! CHECK-NEXT: return diff --git a/flang/test/Lower/HLFIR/minval.f90 b/flang/test/Lower/HLFIR/minval.f90 index 01b0ce77e2d30ea43864784bbaf2b5773d36d46d..2ac9aba850b6f4f96bb6312453083576cb06225e 100644 --- a/flang/test/Lower/HLFIR/minval.f90 +++ b/flang/test/Lower/HLFIR/minval.f90 @@ -254,8 +254,8 @@ end subroutine test_unknown_char_len_result ! CHECK-DAG: %[[C1_7:.*]] = arith.constant 1 : index ! CHECK-DAG: %[[C3_8:.*]] = arith.constant 3 : index ! CHECK-DAG: %[[C3_9:.*]] = arith.constant 3 : index -! CHECK-DAG: %[[ARRAY_BOX:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] -! CHECK: %[[EXPR:.*]] = hlfir.minval %[[ARRAY_BOX]] {fastmath = #arith.fastmath} : (!fir.box>>) -> !hlfir.expr> +! CHECK-DAG: %[[ARRAY_REF:.*]] = hlfir.designate %[[ARRAY]]#0 (%[[C1]]:%[[C3_0]]:%[[C1_3]], %[[C1]]:%[[C3_1]]:%[[C1_5]]) substr %[[C1_7]], %[[C3_8]] shape %[[SHAPE]] typeparams %[[C3_9]] : (!fir.ref>>, index, index, index, index, index, index, index, index, !fir.shape<2>, index) -> !fir.ref>> +! CHECK: %[[EXPR:.*]] = hlfir.minval %[[ARRAY_REF]] {fastmath = #arith.fastmath} : (!fir.ref>>) -> !hlfir.expr> ! CHECK-NEXT: hlfir.assign %[[EXPR]] to %[[RES]]#0 : !hlfir.expr>, !fir.ref> ! CHECK-NEXT: hlfir.destroy %[[EXPR]] ! CHECK-NEXT: return diff --git a/flang/test/Lower/HLFIR/select-rank.f90 b/flang/test/Lower/HLFIR/select-rank.f90 index 7135c248ea44db47cf488f93458651427bc417d7..175c6688e89f3f49b7ee17abf640fcd155f676fc 100644 --- a/flang/test/Lower/HLFIR/select-rank.f90 +++ b/flang/test/Lower/HLFIR/select-rank.f90 @@ -416,7 +416,7 @@ end subroutine ! CHECK: } ! CHECK-LABEL: func.func @_QPtest_rank_star_attributes( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.optional, fir.target}) { +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.asynchronous, fir.bindc_name = "x", fir.optional, fir.target}) { ! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope ! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_rank_star_attributesEx"} : (!fir.box>, !fir.dscope) -> (!fir.box>, !fir.box>) ! CHECK: %[[VAL_3:.*]] = arith.constant 2 : i8 diff --git a/flang/test/Lower/Intrinsics/ieee_rem.f90 b/flang/test/Lower/Intrinsics/ieee_rem.f90 new file mode 100644 index 0000000000000000000000000000000000000000..f6333d5b89dfeb958536b1c88efb908bf020044c --- /dev/null +++ b/flang/test/Lower/Intrinsics/ieee_rem.f90 @@ -0,0 +1,86 @@ +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + +! CHECK-LABEL: c.func @_QQmain + use ieee_arithmetic, only: ieee_rem + + ! CHECK: %[[V_0:[0-9]+]] = fir.alloca f16 {bindc_name = "x2", uniq_name = "_QFEx2"} + ! CHECK: %[[V_1:[0-9]+]]:2 = hlfir.declare %[[V_0]] {uniq_name = "_QFEx2"} : (!fir.ref) -> (!fir.ref, !fir.ref) + ! CHECK: %[[V_2:[0-9]+]] = fir.alloca f32 {bindc_name = "x4", uniq_name = "_QFEx4"} + ! CHECK: %[[V_3:[0-9]+]]:2 = hlfir.declare %[[V_2]] {uniq_name = "_QFEx4"} : (!fir.ref) -> (!fir.ref, !fir.ref) + ! CHECK: %[[V_4:[0-9]+]] = fir.alloca f64 {bindc_name = "x8", uniq_name = "_QFEx8"} + ! CHECK: %[[V_5:[0-9]+]]:2 = hlfir.declare %[[V_4]] {uniq_name = "_QFEx8"} : (!fir.ref) -> (!fir.ref, !fir.ref) + ! CHECK: %[[V_6:[0-9]+]] = fir.alloca f16 {bindc_name = "y2", uniq_name = "_QFEy2"} + ! CHECK: %[[V_7:[0-9]+]]:2 = hlfir.declare %[[V_6]] {uniq_name = "_QFEy2"} : (!fir.ref) -> (!fir.ref, !fir.ref) + ! CHECK: %[[V_8:[0-9]+]] = fir.alloca f32 {bindc_name = "y4", uniq_name = "_QFEy4"} + ! CHECK: %[[V_9:[0-9]+]]:2 = hlfir.declare %[[V_8]] {uniq_name = "_QFEy4"} : (!fir.ref) -> (!fir.ref, !fir.ref) + ! CHECK: %[[V_10:[0-9]+]] = fir.alloca f64 {bindc_name = "y8", uniq_name = "_QFEy8"} + ! CHECK: %[[V_11:[0-9]+]]:2 = hlfir.declare %[[V_10]] {uniq_name = "_QFEy8"} : (!fir.ref) -> (!fir.ref, !fir.ref) + real(2) :: x2, y2 + real(4) :: x4, y4 + real(8) :: x8, y8 + + ! CHECK: hlfir.assign %cst{{[_0-9]*}} to %[[V_3]]#0 : f32, !fir.ref + x4 = 3.3_4 + ! CHECK: hlfir.assign %cst{{[_0-9]*}} to %[[V_9]]#0 : f32, !fir.ref + y4 = -0.0_4 + ! CHECK-DAG: %[[V_12:[0-9]+]] = fir.load %[[V_3]]#0 : !fir.ref + ! CHECK-DAG: %[[V_13:[0-9]+]] = fir.load %[[V_9]]#0 : !fir.ref + ! CHECK-DAG: %[[V_14:[0-9]+]] = fir.convert %[[V_12]] : (f32) -> f32 + ! CHECK-DAG: %[[V_15:[0-9]+]] = fir.convert %[[V_13]] : (f32) -> f32 + ! CHECK-DAG: %[[V_16:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_15]]) <{bit = 516 : i32}> : (f32) -> i1 + ! CHECK-DAG: %[[V_17:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_14]]) <{bit = 144 : i32}> : (f32) -> i1 + ! CHECK-DAG: %[[V_18:[0-9]+]] = arith.andi %[[V_17]], %[[V_16]] : i1 + ! CHECK-DAG: %[[V_19:[0-9]+]] = fir.call @remainderf(%[[V_14]], %[[V_15]]) fastmath : (f32, f32) -> f32 + ! CHECK: fir.if %[[V_18]] { + ! CHECK: %[[V_40:[0-9]+]] = fir.call @_FortranAMapException(%c16{{.*}}) fastmath : (i32) -> i32 + ! CHECK: %[[V_41:[0-9]+]] = fir.call @feraiseexcept(%[[V_40]]) fastmath : (i32) -> i32 + ! CHECK: } + ! CHECK: %[[V_20:[0-9]+]] = fir.convert %[[V_19]] : (f32) -> f32 + ! CHECK: hlfir.assign %[[V_20]] to %[[V_3]]#0 : f32, !fir.ref + x4 = ieee_rem(x4, y4) +! print*, x4 + + ! CHECK: hlfir.assign %cst{{[_0-9]*}} to %[[V_1]]#0 : f16, !fir.ref + x2 = 3.0_2 + ! CHECK: hlfir.assign %cst{{[_0-9]*}} to %[[V_11]]#0 : f64, !fir.ref + y8 = 2.0_8 + ! CHECK-DAG: %[[V_21:[0-9]+]] = fir.load %[[V_1]]#0 : !fir.ref + ! CHECK-DAG: %[[V_22:[0-9]+]] = fir.load %[[V_11]]#0 : !fir.ref + ! CHECK-DAG: %[[V_23:[0-9]+]] = fir.convert %[[V_21]] : (f16) -> f64 + ! CHECK-DAG: %[[V_24:[0-9]+]] = fir.convert %[[V_22]] : (f64) -> f64 + ! CHECK-DAG: %[[V_25:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_24]]) <{bit = 516 : i32}> : (f64) -> i1 + ! CHECK-DAG: %[[V_26:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_23]]) <{bit = 144 : i32}> : (f64) -> i1 + ! CHECK-DAG: %[[V_27:[0-9]+]] = arith.andi %[[V_26]], %[[V_25]] : i1 + ! CHECK-DAG: %[[V_28:[0-9]+]] = fir.call @remainder(%[[V_23]], %[[V_24]]) fastmath : (f64, f64) -> f64 + ! CHECK: fir.if %[[V_27]] { + ! CHECK: %[[V_40:[0-9]+]] = fir.call @_FortranAMapException(%c16{{.*}}) fastmath : (i32) -> i32 + ! CHECK: %[[V_41:[0-9]+]] = fir.call @feraiseexcept(%[[V_40]]) fastmath : (i32) -> i32 + ! CHECK: } + ! CHECK: %[[V_29:[0-9]+]] = fir.convert %[[V_28]] : (f64) -> f64 + ! CHECK: %[[V_30:[0-9]+]] = fir.convert %[[V_29]] : (f64) -> f16 + ! CHECK: hlfir.assign %[[V_30]] to %[[V_1]]#0 : f16, !fir.ref + x2 = ieee_rem(x2, y8) +! print*, x2 + + ! CHECK: hlfir.assign %cst{{[_0-9]*}} to %[[V_5]]#0 : f64, !fir.ref + x8 = huge(x8) + ! CHECK: hlfir.assign %cst{{[_0-9]*}} to %[[V_7]]#0 : f16, !fir.ref + y2 = tiny(y2) + ! CHECK-DAG: %[[V_31:[0-9]+]] = fir.load %[[V_5]]#0 : !fir.ref + ! CHECK-DAG: %[[V_32:[0-9]+]] = fir.load %[[V_7]]#0 : !fir.ref + ! CHECK-DAG: %[[V_33:[0-9]+]] = fir.convert %[[V_31]] : (f64) -> f64 + ! CHECK-DAG: %[[V_34:[0-9]+]] = fir.convert %[[V_32]] : (f16) -> f64 + ! CHECK-DAG: %[[V_35:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_34]]) <{bit = 516 : i32}> : (f64) -> i1 + ! CHECK-DAG: %[[V_36:[0-9]+]] = "llvm.intr.is.fpclass"(%[[V_33]]) <{bit = 144 : i32}> : (f64) -> i1 + ! CHECK-DAG: %[[V_37:[0-9]+]] = arith.andi %[[V_36]], %[[V_35]] : i1 + ! CHECK-DAG: %[[V_38:[0-9]+]] = fir.call @remainder(%[[V_33]], %[[V_34]]) fastmath : (f64, f64) -> f64 + ! CHECK: fir.if %[[V_37]] { + ! CHECK: %[[V_40:[0-9]+]] = fir.call @_FortranAMapException(%c16{{.*}}) fastmath : (i32) -> i32 + ! CHECK: %[[V_41:[0-9]+]] = fir.call @feraiseexcept(%[[V_40]]) fastmath : (i32) -> i32 + ! CHECK: } + ! CHECK: %[[V_39:[0-9]+]] = fir.convert %[[V_38]] : (f64) -> f64 + ! CHECK: hlfir.assign %[[V_39]] to %[[V_5]]#0 : f64, !fir.ref + x8 = ieee_rem(x8, y2) +! print*, x8 + +end diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 new file mode 100644 index 0000000000000000000000000000000000000000..062399d9a19442c2d00ea77c2a7d4af066c38fbf --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 @@ -0,0 +1,8 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=45 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=45 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: DEFAULTMAP clause is not implemented yet +subroutine f00 + !$omp target defaultmap(tofrom:scalar) + !$omp end target +end diff --git a/flang/test/Lower/OpenMP/Todo/depend-clause-depobj.f90 b/flang/test/Lower/OpenMP/Todo/depend-clause-depobj.f90 new file mode 100644 index 0000000000000000000000000000000000000000..3bc730f849192b951da010fd920319752c72f270 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/depend-clause-depobj.f90 @@ -0,0 +1,10 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: INOUTSET, MUTEXINOUTSET and DEPOBJ dependence-types + +subroutine f00(x) + integer :: x + !$omp task depend(depobj: x) + !$omp end task +end diff --git a/flang/test/Lower/OpenMP/Todo/depend-clause-inoutset.f90 b/flang/test/Lower/OpenMP/Todo/depend-clause-inoutset.f90 index 017df006308331bdca071b4ab5b2297bf1c93fdd..160893fccdc5f2d02b69ddbc2973d15c2c7fa20c 100644 --- a/flang/test/Lower/OpenMP/Todo/depend-clause-inoutset.f90 +++ b/flang/test/Lower/OpenMP/Todo/depend-clause-inoutset.f90 @@ -1,7 +1,7 @@ !RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s !RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s -!CHECK: not yet implemented: INOUTSET and MUTEXINOUTSET are not supported yet +!CHECK: not yet implemented: INOUTSET, MUTEXINOUTSET and DEPOBJ dependence-types subroutine f00(x) integer :: x !$omp task depend(inoutset: x) diff --git a/flang/test/Lower/OpenMP/Todo/depend-clause-mutexinoutset.f90 b/flang/test/Lower/OpenMP/Todo/depend-clause-mutexinoutset.f90 index 2f6ff77b20a88c172ec0da58083df1f9cc0e3632..17cc3894c548f17b10ebf8e11eb9e4445ce9a85e 100644 --- a/flang/test/Lower/OpenMP/Todo/depend-clause-mutexinoutset.f90 +++ b/flang/test/Lower/OpenMP/Todo/depend-clause-mutexinoutset.f90 @@ -1,7 +1,7 @@ !RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s !RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s -!CHECK: not yet implemented: INOUTSET and MUTEXINOUTSET are not supported yet +!CHECK: not yet implemented: INOUTSET, MUTEXINOUTSET and DEPOBJ dependence-types subroutine f00(x) integer :: x !$omp task depend(mutexinoutset: x) diff --git a/flang/test/Lower/OpenMP/Todo/loop-directive.f90 b/flang/test/Lower/OpenMP/Todo/loop-directive.f90 deleted file mode 100644 index f1aea70458aa6cf6af96940094fd77ae09118f36..0000000000000000000000000000000000000000 --- a/flang/test/Lower/OpenMP/Todo/loop-directive.f90 +++ /dev/null @@ -1,15 +0,0 @@ -! This test checks lowering of OpenMP loop Directive. - -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s - -! CHECK: not yet implemented: Unhandled directive loop -subroutine test_loop() - integer :: i, j = 1 - !$omp loop - do i=1,10 - j = j + 1 - end do - !$omp end loop -end subroutine - diff --git a/flang/test/Lower/OpenMP/Todo/map-mapper.f90 b/flang/test/Lower/OpenMP/Todo/map-mapper.f90 new file mode 100644 index 0000000000000000000000000000000000000000..d83c20db293072718281d7373f7b86b42e23d5b9 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/map-mapper.f90 @@ -0,0 +1,16 @@ +! RUN: not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 %s 2>&1 | FileCheck %s +program p + integer, parameter :: n = 256 + real(8) :: a(256) + !! TODO: Add declare mapper, when it works to lower this construct + !!type t1 + !! integer :: x + !!end type t1 + !!!$omp declare mapper(xx : t1 :: nn) map(nn, nn%x) + !$omp target map(mapper(xx), from:a) +!CHECK: not yet implemented: OmpMapClause(MAPPER(...)) + do i=1,n + a(i) = 4.2 + end do + !$omp end target +end program p diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5ae48ff736048214795dde86a325edbbc6ab12aa --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 @@ -0,0 +1,47 @@ +! This test checks lowering of OpenMP declare mapper Directive. + +! RUN: split-file %s %t +! RUN: not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-1.f90 2>&1 | FileCheck %t/omp-declare-mapper-1.f90 +! RUN not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-2.f90 2>&1 | FileCheck %t/omp-declare-mapper-2.f90 + +!--- omp-declare-mapper-1.f90 +subroutine declare_mapper_1 + integer,parameter :: nvals = 250 + type my_type + integer :: num_vals + integer, allocatable :: values(:) + end type + + type my_type2 + type (my_type) :: my_type_var + type (my_type) :: temp + real,dimension(nvals) :: unmapped + real,dimension(nvals) :: arr + end type + type (my_type2) :: t + real :: x, y(nvals) + !$omp declare mapper (my_type :: var) map (var, var%values (1:var%num_vals)) +!CHECK: not yet implemented: OpenMPDeclareMapperConstruct +end subroutine declare_mapper_1 + + +!--- omp-declare-mapper-2.f90 +subroutine declare_mapper_2 + integer,parameter :: nvals = 250 + type my_type + integer :: num_vals + integer, allocatable :: values(:) + end type + + type my_type2 + type (my_type) :: my_type_var + type (my_type) :: temp + real,dimension(nvals) :: unmapped + real,dimension(nvals) :: arr + end type + type (my_type2) :: t + real :: x, y(nvals) + !$omp declare mapper (my_mapper : my_type2 :: v) map (v%arr, x, y(:)) & + !$omp& map (alloc : v%temp) +!CHECK: not yet implemented: OpenMPDeclareMapperConstruct +end subroutine declare_mapper_2 diff --git a/flang/test/Lower/OpenMP/Todo/reduction-inscan.f90 b/flang/test/Lower/OpenMP/Todo/reduction-inscan.f90 index c5f196fe09693a4ab8b1f4796bf6fb86e553d95c..152d91a16f80fe83fee61a20caef5570ad2275b1 100644 --- a/flang/test/Lower/OpenMP/Todo/reduction-inscan.f90 +++ b/flang/test/Lower/OpenMP/Todo/reduction-inscan.f90 @@ -8,6 +8,7 @@ subroutine reduction_inscan() !$omp do reduction(inscan, +:i) do j=1,10 + !$omp scan inclusive(i) i = i + 1 end do !$omp end do diff --git a/flang/test/Lower/OpenMP/Todo/reduction-modifiers.f90 b/flang/test/Lower/OpenMP/Todo/reduction-modifiers.f90 index 5e566466492ceb961fee1983a38b4d60780760d0..82625ed8c5f31c1ee3607ebb3c1842095329838d 100644 --- a/flang/test/Lower/OpenMP/Todo/reduction-modifiers.f90 +++ b/flang/test/Lower/OpenMP/Todo/reduction-modifiers.f90 @@ -8,6 +8,7 @@ subroutine foo() j = 0 !$omp do reduction (inscan, *: j) do i = 1, 10 + !$omp scan inclusive(j) j = j + 1 end do end subroutine diff --git a/flang/test/Lower/OpenMP/Todo/scope-allocate.f90 b/flang/test/Lower/OpenMP/Todo/scope-allocate.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5a834c81a852cff3e32ae04c518917b462de9df0 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/scope-allocate.f90 @@ -0,0 +1,12 @@ +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s -fopenmp-version=52 2>&1 | FileCheck %s + +! CHECK: not yet implemented: Scope construct +program omp_scope + integer i + i = 10 + + !$omp scope allocate(x) private(x) + print *, "omp scope", i + !$omp end scope + +end program omp_scope diff --git a/flang/test/Lower/OpenMP/Todo/scope-firstprivate.f90 b/flang/test/Lower/OpenMP/Todo/scope-firstprivate.f90 new file mode 100644 index 0000000000000000000000000000000000000000..87bcecb817da494b7e826518349e66b17a907e5f --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/scope-firstprivate.f90 @@ -0,0 +1,12 @@ +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s -fopenmp-version=52 2>&1 | FileCheck %s + +! CHECK: not yet implemented: Scope construct +program omp_scope + integer i + i = 10 + + !$omp scope firstprivate(x) + print *, "omp scope", i + !$omp end scope + +end program omp_scope diff --git a/flang/test/Lower/OpenMP/Todo/task_detach.f90 b/flang/test/Lower/OpenMP/Todo/task_detach.f90 index 6bc55e9e7cf64c897ff4060128219031ce287f3a..cb6943073d4b3a96ba0e11a7ff9c9b8fd299c3be 100644 --- a/flang/test/Lower/OpenMP/Todo/task_detach.f90 +++ b/flang/test/Lower/OpenMP/Todo/task_detach.f90 @@ -6,7 +6,7 @@ ! `detach` clause !=============================================================================== -! CHECK: not yet implemented: OpenMP Block construct clause +! CHECK: not yet implemented: DETACH clause is not implemented yet subroutine omp_task_detach() use omp_lib integer (kind=omp_event_handle_kind) :: event diff --git a/flang/test/Lower/OpenMP/Todo/task_untied.f90 b/flang/test/Lower/OpenMP/Todo/task_untied.f90 index 19621c7aac16d6ed6e144c33be81792ff275f67e..87d242ba3e9d21feab06417a986ae72d15eda302 100644 --- a/flang/test/Lower/OpenMP/Todo/task_untied.f90 +++ b/flang/test/Lower/OpenMP/Todo/task_untied.f90 @@ -5,7 +5,7 @@ ! `untied` clause !=============================================================================== -! CHECK: not yet implemented: OpenMP Block construct clause +! CHECK: not yet implemented: UNTIED clause is not implemented yet subroutine omp_task_untied() !$omp task untied call foo() diff --git a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 index 87ca400e82e23fc9c219eb72001c73a536d142ee..e162c5a2d6d69f75bd8918db9e0e8b1ea739e216 100644 --- a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 +++ b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 @@ -24,7 +24,7 @@ !HOST: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound(%[[LB_1]] : index) upper_bound(%[[UB_1]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_1]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.llvm_ptr>> {name = ""} -!HOST: %[[MAP_INFO_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "sp_read(2:5)"} +!HOST: %[[MAP_INFO_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "sp_read(2:5)"} !HOST: %[[LOAD_3:.*]] = fir.load %[[DECLARE_2]]#0 : !fir.ref>>> !HOST: %[[LOAD_4:.*]] = fir.load %[[DECLARE_2]]#1 : !fir.ref>>> @@ -42,7 +42,7 @@ !HOST: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound(%[[LB_2]] : index) upper_bound(%[[UB_2]] : index) extent(%[[BOX_5]]#1 : index) stride(%[[BOX_4]]#2 : index) start_idx(%[[BOX_3]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_2]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.llvm_ptr>> {name = ""} -!HOST: %[[MAP_INFO_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "sp_write(2:5)"} +!HOST: %[[MAP_INFO_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "sp_write(2:5)"} subroutine read_write_section() integer, allocatable :: sp_read(:) @@ -81,7 +81,7 @@ module assumed_allocatable_array_routines !HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[LB]] : index) upper_bound(%[[UB]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} -!HOST: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "arr_read_write(2:5)"} +!HOST: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref>>> {name = "arr_read_write(2:5)"} subroutine assumed_shape_array(arr_read_write) integer, allocatable, intent(inout) :: arr_read_write(:) diff --git a/flang/test/Lower/OpenMP/allocatable-map.f90 b/flang/test/Lower/OpenMP/allocatable-map.f90 index a9f576a6f0999234e65d10f76b8f6d6770c20762..64b000a4950c2c5981f4a2f00187091752bd22af 100644 --- a/flang/test/Lower/OpenMP/allocatable-map.f90 +++ b/flang/test/Lower/OpenMP/allocatable-map.f90 @@ -3,8 +3,8 @@ !HLFIRDIALECT: %[[POINTER:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFpointer_routineEpoint"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !HLFIRDIALECT: %[[BOX_OFF:.*]] = fir.box_offset %[[POINTER]]#1 base_addr : (!fir.ref>>) -> !fir.llvm_ptr> !HLFIRDIALECT: %[[POINTER_MAP_MEMBER:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref>>, i32) var_ptr_ptr(%[[BOX_OFF]] : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} -!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> {name = "point"} -!HLFIRDIALECT: omp.target map_entries(%[[POINTER_MAP_MEMBER]] -> {{.*}}, %[[POINTER_MAP]] -> {{.*}} : !fir.llvm_ptr>, !fir.ref>>) { +!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> {name = "point"} +!HLFIRDIALECT: omp.target map_entries(%[[POINTER_MAP]] -> {{.*}}, %[[POINTER_MAP_MEMBER]] -> {{.*}} : !fir.ref>>, !fir.llvm_ptr>) { subroutine pointer_routine() integer, pointer :: point !$omp target map(tofrom:point) diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90 index 09498ca6cdde992ff8b0fac690a1ec683d202609..78fa81567ca54c595ec4e94eae523058f828be28 100644 --- a/flang/test/Lower/OpenMP/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/array-bounds.f90 @@ -52,8 +52,8 @@ module assumed_array_routines !HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %0 base_addr : (!fir.ref>>) -> !fir.llvm_ptr>> !HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} -!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref> {name = "arr_read_write(2:5)"} -!HOST: omp.target map_entries(%[[MAP_INFO_MEMBER]] -> %{{.*}}, %[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.llvm_ptr>>, !fir.ref>, !fir.ref) { +!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : [0] : !fir.llvm_ptr>>) -> !fir.ref> {name = "arr_read_write(2:5)"} +!HOST: omp.target map_entries(%[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}}, %[[MAP_INFO_MEMBER]] -> %{{.*}} : !fir.ref>, !fir.ref, !fir.llvm_ptr>>) { subroutine assumed_shape_array(arr_read_write) integer, intent(inout) :: arr_read_write(:) diff --git a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 index 3459be87fea2f0f50e1c8da10ab225e3e47e5e02..cfdcd9eda82d1da3e74b37615e91469f19b10645 100644 --- a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 +++ b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 @@ -35,7 +35,7 @@ program test_link allocate(test_ptr1) test_ptr1 = 1 - !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr1"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, to) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr1"} !$omp target test_ptr1 = test_ptr1 + 1 !$omp end target @@ -46,7 +46,7 @@ program test_link !$omp end target - !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr2"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, to) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr2"} test_ptr2 => test_target !$omp target test_ptr2 = test_ptr2 + 1 diff --git a/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 b/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 new file mode 100644 index 0000000000000000000000000000000000000000..47bcf2a7229ea54a5261b6df184d74f478a73977 --- /dev/null +++ b/flang/test/Lower/OpenMP/derived-type-allocatable-map.f90 @@ -0,0 +1,161 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +!CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.type<[[ONE_LAYER_TY:_QFdtype_alloca_map_op_blockTone_layer{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}]]> {{.*}} +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {{{.*}}} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +!CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} +!CHECK: %[[MEMBER_INDEX:.*]] = arith.constant 4 : index +!CHECK: %[[MEMBER_COORD:.*]] = fir.coordinate_of %[[DECLARE]]#0, %[[MEMBER_INDEX]] : (!fir.ref>, index) -> !fir.ref>>> +!CHECK: %[[MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[MEMBER_COORD]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +!CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +!CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +!CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>, !fir.type<[[ONE_LAYER_TY]]>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_DESCRIPTOR]], %[[MAP_MEMBER_BASE_ADDR]] : [4], [4, 0] : !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref> {{{.*}} partial_map = true} +!CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG0:.*]], %[[MAP_MEMBER_DESCRIPTOR]] -> %[[ARG1:.*]], %[[MAP_MEMBER_BASE_ADDR]] -> %[[ARG2:.*]] : !fir.ref>, !fir.ref>>>, !fir.llvm_ptr>>) { +!CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{{.*}}} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +subroutine dtype_alloca_map_op_block() + type :: one_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + end type one_layer + + type(one_layer) :: one_l + + allocate(one_l%array_j(10)) + + !$omp target map(tofrom: one_l%array_j) + one_l%array_j(1) = 10 + !$omp end target +end subroutine + +!CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}]]>>> {{.*}} +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {{{.*}}} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +!CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} +!CHECK: %[[LOAD_DTYPE:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref>>> +!CHECK: %[[MEMBER_INDEX:.*]] = arith.constant 4 : index +!CHECK: %[[MEMBER_COORD:.*]] = fir.coordinate_of %[[LOAD_DTYPE]], %[[MEMBER_INDEX]] : (!fir.box>>, index) -> !fir.ref>>> +!CHECK: %[[MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[MEMBER_COORD]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +!CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +!CHECK: %[[MAP_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +!CHECK: %[[LOAD_DTYPE:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref>>> +!CHECK: %[[MEMBER_COORD:.*]] = arith.constant 5 : index +!CHECK: %[[REGULAR_MEMBER:.*]] = fir.coordinate_of %[[LOAD_DTYPE]], %[[MEMBER_COORD]] : (!fir.box>>, index) -> !fir.ref +!CHECK: %[[MAP_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[REGULAR_MEMBER]] : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {{.*}} +!CHECK: %[[DTYPE_BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +!CHECK: %[[MAP_DTYPE_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.type<[[REC_TY]]>) var_ptr_ptr(%[[DTYPE_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr>> {{.*}} +!CHECK: %[[MAP_DTYPE_DESC:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) members(%[[MAP_DTYPE_BASE_ADDR]], %[[MAP_MEMBER_DESC]], %[[MAP_MEMBER_BASE_ADDR]], %[[MAP_REGULAR_MEMBER]] : [0], [0, 4], [0, 4, 0], [0, 5] : !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) -> !fir.ref>>> {{.*}} +!CHECK: omp.target map_entries(%[[MAP_DTYPE_DESC]] -> %[[ARG0:.*]], %[[MAP_DTYPE_BASE_ADDR]] -> %[[ARG1:.*]], %[[MAP_MEMBER_DESC]] -> %[[ARG2:.*]], %[[MAP_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]], %[[MAP_REGULAR_MEMBER]] -> %[[ARG4:.*]] : !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) { +!CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{{.*}}} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +subroutine alloca_dtype_op_block_add() + type :: one_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + end type one_layer + + type(one_layer), allocatable :: one_l + + allocate(one_l) + allocate(one_l%array_j(10)) + + !$omp target map(tofrom: one_l%array_j, one_l%k) + one_l%array_j(1) = 10 + one_l%k = 20 + !$omp end target +end subroutine + +!CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFalloca_nest_dype_map_op_block_addTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}]]>}>>> {{.*}} +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]] {{.*}} : (!fir.ref}>>>>) -> (!fir.ref}>>>>, !fir.ref}>>>>) +!CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} +!CHECK: %[[LOAD:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref}>>>> +!CHECK: %[[NESTED_DTYPE_INDEX:.*]] = arith.constant 6 : index +!CHECK: %[[NESTED_DTYPE_COORD:.*]] = fir.coordinate_of %[[LOAD]], %[[NESTED_DTYPE_INDEX]] : (!fir.box}>>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}]]>> +!CHECK: %[[NESTED_MEMBER_INDEX:.*]] = arith.constant 2 : index +!CHECK: %[[NESTED_MEMBER_COORD:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], %[[NESTED_MEMBER_INDEX]] : (!fir.ref>, index) -> !fir.ref>>> +!CHECK: %[[NESTED_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[NESTED_MEMBER_COORD]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +!CHECK: %[[MAP_NESTED_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[NESTED_MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +!CHECK: %[[MAP_NESTED_MEMBER_COORD:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +!CHECK: %[[LOAD:.*]] = fir.load %[[DECLARE]]#0 : !fir.ref}>>>> +!CHECK: %[[NESTED_DTYPE_INDEX:.*]] = arith.constant 6 : index +!CHECK: %[[NESTED_DTYPE_COORD:.*]] = fir.coordinate_of %[[LOAD]], %[[NESTED_DTYPE_INDEX]] : (!fir.box}>>>, index) -> !fir.ref> +!CHECK: %[[NESTED_MEMBER_INDEX:.*]] = arith.constant 3 : index +!CHECK: %[[REGULAR_NESTED_MEMBER_COORD:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], %[[NESTED_MEMBER_INDEX]] : (!fir.ref>, index) -> !fir.ref +!CHECK: %[[MAP_REGULAR_NESTED_MEMBER:.*]] = omp.map.info var_ptr(%[[REGULAR_NESTED_MEMBER_COORD]] : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {{.*}} +!CHECK: %[[DTYPE_BASE_ADDR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref}>>>>) -> !fir.llvm_ptr}>>> +!CHECK: %[[MAP_DTYPE_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref}>>>>, !fir.type<[[REC_TY]]>}>) var_ptr_ptr(%[[DTYPE_BASE_ADDR]] : !fir.llvm_ptr}>>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr}>>> {{.*}} +!CHECK: %[[MAP_DTYPE:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref}>>>>, !fir.box}>>>) map_clauses(to) capture(ByRef) members(%[[MAP_DTYPE_BASE_ADDR]], %[[MAP_NESTED_MEMBER_COORD]], %[[MAP_NESTED_MEMBER_BASE_ADDR]], %[[MAP_REGULAR_NESTED_MEMBER]] : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !fir.llvm_ptr}>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) -> !fir.ref}>>>> {{.*}} +!CHECK: omp.target map_entries(%[[MAP_DTYPE]] -> %[[ARG0:.*]], %[[MAP_DTYPE_BASE_ADDR]] -> %[[ARG1:.*]], %[[MAP_NESTED_MEMBER_COORD]] -> %[[ARG2:.*]], %[[MAP_NESTED_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]], %[[MAP_REGULAR_NESTED_MEMBER]] -> %[[ARG4:.*]] : !fir.ref}>>>>, !fir.llvm_ptr}>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) { +!CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref}>>>>) -> (!fir.ref}>>>>, !fir.ref}>>>>) +subroutine alloca_nest_dype_map_op_block_add() + type :: middle_layer + real(4) :: i + integer(4) :: array_i(10) + integer, allocatable :: array_k(:) + integer(4) :: k + end type middle_layer + + type :: top_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + type(middle_layer) :: nest + end type top_layer + + type(top_layer), allocatable :: one_l + + allocate(one_l) + allocate(one_l%nest%array_k(10)) + + !$omp target map(tofrom: one_l%nest%array_k, one_l%nest%k) + one_l%nest%array_k(1) = 10 + one_l%nest%k = 20 + !$omp end target +end subroutine + +!CHECK: %[[ALLOCA]] = fir.alloca !fir.type<[[REC_TY:_QFnest_dtype_alloca_map_op_block_addTtop_layer{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFnest_dtype_alloca_map_op_block_addTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}]]> {{.*}} +!CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA:.*]] {{.*}} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +!CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) {stride_in_bytes = true} +!CHECK: %[[NESTED_DTYPE_INDEX:.*]] = arith.constant 6 : index +!CHECK: %[[NESTED_DTYPE_COORD:.*]] = fir.coordinate_of %[[DECLARE]]#0, %[[NESTED_DTYPE_INDEX]] : (!fir.ref>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}]]>> +!CHECK: %[[NESTED_MEMBER_INDEX:.*]] = arith.constant 2 : index +!CHECK: %[[NESTED_MEMBER_COORD:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], %[[NESTED_MEMBER_INDEX]] : (!fir.ref>, index) -> !fir.ref>>> +!CHECK: %[[NESTED_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[NESTED_MEMBER_COORD]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +!CHECK: %[[MAP_NESTED_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[NESTED_MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +!CHECK: %[[MAP_NESTED_MEMBER_DESC:.*]] = omp.map.info var_ptr(%[[NESTED_MEMBER_COORD]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +!CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_NESTED_MEMBER_DESC]], %[[MAP_NESTED_MEMBER_BASE_ADDR]] : [6, 2], [6, 2, 0] : !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref> {{.*}} +!CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG0:.*]], %[[MAP_NESTED_MEMBER_DESC]] -> %[[ARG1:.*]], %[[MAP_NESTED_MEMBER_BASE_ADDR]] -> %[[ARG2:.*]] : !fir.ref>, !fir.ref>>>, !fir.llvm_ptr>>) { +!CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +subroutine nest_dtype_alloca_map_op_block_add() + type :: middle_layer + real(4) :: i + integer(4) :: array_i(10) + integer, allocatable :: array_k(:) + integer(4) :: k + end type middle_layer + + type :: top_layer + real(4) :: i + integer, allocatable :: scalar + integer(4) :: array_i(10) + real(4) :: j + integer, allocatable :: array_j(:) + integer(4) :: k + type(middle_layer) :: nest + end type top_layer + + type(top_layer) :: one_l + + allocate(one_l%nest%array_k(10)) + + !$omp target map(tofrom: one_l%nest%array_k) + one_l%nest%array_k(1) = 25 + !$omp end target +end subroutine diff --git a/flang/test/Lower/OpenMP/derived-type-map.f90 b/flang/test/Lower/OpenMP/derived-type-map.f90 index d1eed74a4270ce226d744e691b9e9702cb2b1c63..e6a3b9ada762bc37e03d64fc983cb5c0640a7f48 100644 --- a/flang/test/Lower/OpenMP/derived-type-map.f90 +++ b/flang/test/Lower/OpenMP/derived-type-map.f90 @@ -41,7 +41,7 @@ end subroutine mapType_derived_explicit !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) !CHECK: %[[MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[MEMBER]] : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "scalar_arr%array"} !CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref,int:i32}>>, !fir.type<_QFmaptype_derived_explicit_single_memberTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP]] : [1] : !fir.ref>) -> !fir.ref,int:i32}>> {name = "scalar_arr", partial_map = true} -!CHECK: omp.target map_entries(%[[MEMBER_MAP]] -> %[[ARG0:.*]], %[[PARENT_MAP]] -> %[[ARG1:.*]] : !fir.ref>, !fir.ref,int:i32}>>) { +!CHECK: omp.target map_entries(%[[PARENT_MAP]] -> %[[ARG0:.*]], %[[MEMBER_MAP]] -> %[[ARG1:.*]] : !fir.ref,int:i32}>>, !fir.ref>) { subroutine mapType_derived_explicit_single_member type :: scalar_and_array real(4) :: real @@ -62,7 +62,7 @@ end subroutine mapType_derived_explicit_single_member !CHECK: %[[MEMBER2:.*]] = hlfir.designate %[[DECLARE]]#0{"real"} : (!fir.ref,int:i32}>>) -> !fir.ref !CHECK: %[[MEMBER_MAP_2:.*]] = omp.map.info var_ptr(%[[MEMBER2]] : !fir.ref, f32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "scalar_arr%real"} !CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref,int:i32}>>, !fir.type<_QFmaptype_derived_explicit_multiple_membersTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP_1]], %[[MEMBER_MAP_2]] : [2], [0] : !fir.ref, !fir.ref) -> !fir.ref,int:i32}>> {name = "scalar_arr", partial_map = true} -!CHECK: omp.target map_entries(%[[MEMBER_MAP_1]] -> %[[ARG0:.*]], %[[MEMBER_MAP_2]] -> %[[ARG1:.*]], %[[PARENT_MAP]] -> %[[ARG2:.*]] : !fir.ref, !fir.ref, !fir.ref,int:i32}>>) { +!CHECK: omp.target map_entries(%[[PARENT_MAP]] -> %[[ARG0:.*]], %[[MEMBER_MAP_1]] -> %[[ARG1:.*]], %[[MEMBER_MAP_2]] -> %[[ARG2:.*]] : !fir.ref,int:i32}>>, !fir.ref, !fir.ref) { subroutine mapType_derived_explicit_multiple_members type :: scalar_and_array real(4) :: real @@ -85,7 +85,7 @@ end subroutine mapType_derived_explicit_multiple_members !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[LB]] : index) upper_bound(%[[UB]] : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) !CHECK: %[[MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[MEMBER]] : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%20) -> !fir.ref> {name = "scalar_arr%array(2:5)"} !CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref,int:i32}>>, !fir.type<_QFmaptype_derived_explicit_member_with_boundsTscalar_and_array{real:f32,array:!fir.array<10xi32>,int:i32}>) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP]] : [1] : !fir.ref>) -> !fir.ref,int:i32}>> {name = "scalar_arr", partial_map = true} -!CHECK: omp.target map_entries(%[[MEMBER_MAP]] -> %[[ARG0:.*]], %[[PARENT_MAP]] -> %[[ARG1:.*]] : !fir.ref>, !fir.ref,int:i32}>>) { +!CHECK: omp.target map_entries(%[[PARENT_MAP]] -> %[[ARG0:.*]], %[[MEMBER_MAP]] -> %[[ARG1:.*]] : !fir.ref,int:i32}>>, !fir.ref>) { subroutine mapType_derived_explicit_member_with_bounds type :: scalar_and_array real(4) :: real @@ -105,8 +105,8 @@ end subroutine mapType_derived_explicit_member_with_bounds !CHECK: %[[NEST_MEMBER:.*]] = hlfir.designate %[[NEST]]{"array"} shape %{{.*}} : (!fir.ref}>>, !fir.shape<1>) -> !fir.ref> !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) !CHECK: %[[MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[NEST_MEMBER]] : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "scalar_arr%nest%array"} -!CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) members(%35 : [2,2] : !fir.ref>) -> {{.*}} {name = "scalar_arr", partial_map = true} -!CHECK: omp.target map_entries(%[[MEMBER_MAP]] -> %[[ARG0:.*]], %[[PARENT_MAP]] -> %[[ARG1:.*]] : {{.*}}, {{.*}}) { +!CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) members(%35 : [2, 2] : !fir.ref>) -> {{.*}} {name = "scalar_arr", partial_map = true} +!CHECK: omp.target map_entries(%[[PARENT_MAP]] -> %[[ARG0:.*]], %[[MEMBER_MAP]] -> %[[ARG1:.*]] : {{.*}}, {{.*}}) { subroutine mapType_derived_nested_explicit_single_member type :: nested integer(4) :: int @@ -136,8 +136,8 @@ end subroutine mapType_derived_nested_explicit_single_member !CHECK: %[[NEST:.*]] = hlfir.designate %[[DECLARE]]#0{"nest"} : ({{.*}}) -> {{.*}} !CHECK: %[[NEST_MEMBER2:.*]] = hlfir.designate %[[NEST]]{"real"} : ({{.*}}) -> !fir.ref !CHECK: %[[MEMBER_MAP_2:.*]] = omp.map.info var_ptr(%[[NEST_MEMBER2]] : !fir.ref, f32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "scalar_arr%nest%real"} -!CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP_1]], %[[MEMBER_MAP_2]] : [2,0], [2,1] : !fir.ref, !fir.ref) -> {{.*}} {name = "scalar_arr", partial_map = true} -!CHECK: omp.target map_entries(%[[MEMBER_MAP_1]] -> %[[ARG0:.*]], %[[MEMBER_MAP_2]] -> %[[ARG1:.*]], %[[PARENT_MAP]] -> %[[ARG2:.*]] : !fir.ref, !fir.ref, {{.*}}) { +!CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP_1]], %[[MEMBER_MAP_2]] : [2, 0], [2, 1] : !fir.ref, !fir.ref) -> {{.*}} {name = "scalar_arr", partial_map = true} +!CHECK: omp.target map_entries(%[[PARENT_MAP]] -> %[[ARG0:.*]], %[[MEMBER_MAP_1]] -> %[[ARG1:.*]], %[[MEMBER_MAP_2]] -> %[[ARG2:.*]] : {{.*}}, !fir.ref, !fir.ref) { subroutine mapType_derived_nested_explicit_multiple_members type :: nested integer(4) :: int @@ -169,8 +169,8 @@ end subroutine mapType_derived_nested_explicit_multiple_members !CHECK: %[[C4:.*]] = arith.constant 4 : index !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C1_2]] : index) upper_bound(%[[C4]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) !CHECK: %[[MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[NEST_MEMBER]] : !fir.ref>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref> {name = "scalar_arr%nest%array(2:5)"} -!CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP]] : [2,2] : !fir.ref>) -> {{.*}} {name = "scalar_arr", partial_map = true} -!CHECK: omp.target map_entries(%[[MEMBER_MAP]] -> %[[ARG0:.*]], %[[PARENT_MAP]] -> %[[ARG1:.*]] : !fir.ref>, {{.*}}) { +!CHECK: %[[PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MEMBER_MAP]] : [2, 2] : !fir.ref>) -> {{.*}} {name = "scalar_arr", partial_map = true} +!CHECK: omp.target map_entries(%[[PARENT_MAP]] -> %[[ARG0:.*]], %[[MEMBER_MAP]] -> %[[ARG1:.*]] : {{.*}}, !fir.ref>) { subroutine mapType_derived_nested_explicit_member_with_bounds type :: nested integer(4) :: int @@ -202,9 +202,9 @@ end subroutine mapType_derived_nested_explicit_member_with_bounds !CHECK: %[[PARENT_2:.*]] = hlfir.designate %[[DECLARE_2]]#0{"nest"} : {{.*}} -> {{.*}} !CHECK: %[[MEMBER_2:.*]] = hlfir.designate %[[PARENT_2]]{"int"} : {{.*}} -> !fir.ref !CHECK: %[[MAP_MEMBER_2:.*]] = omp.map.info var_ptr(%[[MEMBER_2]] : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "scalar_arr2%nest%int"} -!CHECK: %[[MAP_PARENT_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_1]] : [2,0] : !fir.ref) -> {{.*}} {name = "scalar_arr1", partial_map = true} -!CHECK: %[[MAP_PARENT_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_2]] : [2,0] : !fir.ref) -> {{.*}} {name = "scalar_arr2", partial_map = true} -!CHECK: omp.target map_entries(%[[MAP_MEMBER_1]] -> %[[ARG0:.*]], %[[MAP_PARENT_1]] -> %[[ARG1:.*]], %[[MAP_MEMBER_2]] -> %[[ARG2:.*]], %[[MAP_PARENT_2:.*]] -> %[[ARG3:.*]] : !fir.ref, {{.*}}, !fir.ref, {{.*}}) { +!CHECK: %[[MAP_PARENT_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_1]] : [2, 0] : !fir.ref) -> {{.*}} {name = "scalar_arr1", partial_map = true} +!CHECK: %[[MAP_PARENT_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_2]] : [2, 0] : !fir.ref) -> {{.*}} {name = "scalar_arr2", partial_map = true} +!CHECK: omp.target map_entries(%[[MAP_PARENT_1]] -> %[[ARG0:.*]], %[[MAP_PARENT_2:.*]] -> %[[ARG1:.*]], %[[MAP_MEMBER_1]] -> %[[ARG2:.*]], %[[MAP_MEMBER_2]] -> %[[ARG3:.*]] : {{.*}}, {{.*}}, !fir.ref, !fir.ref) { subroutine mapType_multilpe_derived_nested_explicit_member type :: nested integer(4) :: int diff --git a/flang/test/Lower/OpenMP/loop-directive.f90 b/flang/test/Lower/OpenMP/loop-directive.f90 new file mode 100644 index 0000000000000000000000000000000000000000..4b4d640e449eeb7f8164306ef354d51d384d9451 --- /dev/null +++ b/flang/test/Lower/OpenMP/loop-directive.f90 @@ -0,0 +1,102 @@ +! This test checks lowering of OpenMP loop Directive. + +! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s + +! CHECK: omp.declare_reduction @[[RED:add_reduction_i32]] : i32 +! CHECK: omp.private {type = private} @[[DUMMY_PRIV:.*test_privateEdummy_private.*]] : !fir.ref +! CHECK: omp.private {type = private} @[[I_PRIV:.*test_no_clausesEi.*]] : !fir.ref + +! CHECK-LABEL: func.func @_QPtest_no_clauses +subroutine test_no_clauses() + integer :: i, j, dummy = 1 + + ! CHECK: omp.loop private(@[[I_PRIV]] %{{.*}}#0 -> %[[ARG:.*]] : !fir.ref) { + ! CHECK-NEXT: omp.loop_nest (%[[IV:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} { + ! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] + ! CHECK: fir.store %[[IV]] to %[[ARG_DECL]]#1 : !fir.ref + ! CHECK: } + ! CHECK: } + !$omp loop + do i=1,10 + dummy = dummy + 1 + end do + !$omp end loop +end subroutine + +! CHECK-LABEL: func.func @_QPtest_collapse +subroutine test_collapse() + integer :: i, j, dummy = 1 + ! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) { + ! CHECK-NEXT: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 {{.*}} { + ! CHECK: } + ! CHECK: } + !$omp loop collapse(2) + do i=1,10 + do j=2,20 + dummy = dummy + 1 + end do + end do + !$omp end loop +end subroutine + +! CHECK-LABEL: func.func @_QPtest_private +subroutine test_private() + integer :: i, dummy = 1 + ! CHECK: omp.loop private(@[[DUMMY_PRIV]] %{{.*}}#0 -> %[[DUMMY_ARG:.*]], @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) { + ! CHECK-NEXT: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} { + ! CHECK: %[[DUMMY_DECL:.*]]:2 = hlfir.declare %[[DUMMY_ARG]] {uniq_name = "_QFtest_privateEdummy"} + ! CHECK: %{{.*}} = fir.load %[[DUMMY_DECL]]#0 + ! CHECK: hlfir.assign %{{.*}} to %[[DUMMY_DECL]]#0 + ! CHECK: } + ! CHECK: } + !$omp loop private(dummy) + do i=1,10 + dummy = dummy + 1 + end do + !$omp end loop +end subroutine + + +! CHECK-LABEL: func.func @_QPtest_order +subroutine test_order() + integer :: i, dummy = 1 + ! CHECK: omp.loop order(reproducible:concurrent) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) { + ! CHECK: } + !$omp loop order(concurrent) + do i=1,10 + dummy = dummy + 1 + end do + !$omp end loop +end subroutine + +! CHECK-LABEL: func.func @_QPtest_reduction +subroutine test_reduction() + integer :: i, dummy = 1 + + ! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}} : !{{.*}}) reduction + ! CHECK-SAME: (@[[RED]] %{{.*}}#0 -> %[[DUMMY_ARG:.*]] : !{{.*}}) { + ! CHECK-NEXT: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} { + ! CHECK: %[[DUMMY_DECL:.*]]:2 = hlfir.declare %[[DUMMY_ARG]] {uniq_name = "_QFtest_reductionEdummy"} + ! CHECK: %{{.*}} = fir.load %[[DUMMY_DECL]]#0 + ! CHECK: hlfir.assign %{{.*}} to %[[DUMMY_DECL]]#0 + ! CHECK: } + ! CHECK: } + !$omp loop reduction(+:dummy) + do i=1,10 + dummy = dummy + 1 + end do + !$omp end loop +end subroutine + +! CHECK-LABEL: func.func @_QPtest_bind +subroutine test_bind() + integer :: i, dummy = 1 + ! CHECK: omp.loop bind(thread) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) { + ! CHECK: } + !$omp loop bind(thread) + do i=1,10 + dummy = dummy + 1 + end do + !$omp end loop +end subroutine diff --git a/flang/test/Lower/OpenMP/map-component-ref.f90 b/flang/test/Lower/OpenMP/map-component-ref.f90 index 79b5605378d38efa7058215b268122c253de4872..b7a7ee06b02f293f6396ae9e4a667b8724c71c34 100644 --- a/flang/test/Lower/OpenMP/map-component-ref.f90 +++ b/flang/test/Lower/OpenMP/map-component-ref.f90 @@ -7,8 +7,8 @@ ! CHECK: %[[V2:[0-9]+]] = hlfir.designate %[[V1]]#0{"a1"} : (!fir.ref>) -> !fir.ref ! CHECK: %[[V3:[0-9]+]] = omp.map.info var_ptr(%[[V2]] : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "a%a1"} ! CHECK: %[[V4:[0-9]+]] = omp.map.info var_ptr(%[[V1]]#1 : !fir.ref>, !fir.type<_QFfoo1Tt0{a0:i32,a1:i32}>) map_clauses(tofrom) capture(ByRef) members(%[[V3]] : [1] : !fir.ref) -> !fir.ref> {name = "a", partial_map = true} -! CHECK: omp.target map_entries(%[[V3]] -> %arg0, %[[V4]] -> %arg1 : !fir.ref, !fir.ref>) { -! CHECK: %[[V5:[0-9]+]]:2 = hlfir.declare %arg1 {uniq_name = "_QFfoo1Ea"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: omp.target map_entries(%[[V4]] -> %arg0, %[[V3]] -> %arg1 : !fir.ref>, !fir.ref) { +! CHECK: %[[V5:[0-9]+]]:2 = hlfir.declare %arg0 {uniq_name = "_QFfoo1Ea"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: %c0_i32 = arith.constant 0 : i32 ! CHECK: %[[V6:[0-9]+]] = hlfir.designate %[[V5]]#0{"a1"} : (!fir.ref>) -> !fir.ref ! CHECK: hlfir.assign %c0_i32 to %[[V6]] : i32, !fir.ref diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90 index 54189cdef1e8156218c9ac190ba9b29a7ddd5d22..04764be2293c1f845516d112c348770086f9901f 100644 --- a/flang/test/Lower/OpenMP/target.f90 +++ b/flang/test/Lower/OpenMP/target.f90 @@ -525,12 +525,12 @@ subroutine omp_target_device_addr !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} - !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) members(%[[MAP_MEMBERS]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} !CHECK: %[[DEV_ADDR_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} - !CHECK: %[[DEV_ADDR:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[DEV_ADDR_MEMBERS]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} - !CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[DEV_ADDR_MEMBERS]] -> %[[ARG_0:.*]], %[[DEV_ADDR]] -> %[[ARG_1:.*]] : !fir.llvm_ptr>, !fir.ref>>) { + !CHECK: %[[DEV_ADDR:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) members(%[[DEV_ADDR_MEMBERS]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> {name = "a"} + !CHECK: omp.target_data map_entries(%[[MAP]], %[[MAP_MEMBERS]] : {{.*}}) use_device_addr(%[[DEV_ADDR]] -> %[[ARG_0:.*]], %[[DEV_ADDR_MEMBERS]] -> %[[ARG_1:.*]] : !fir.ref>>, !fir.llvm_ptr>) { !$omp target data map(tofrom: a) use_device_addr(a) - !CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[ARG_1]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + !CHECK: %[[VAL_1_DECL:.*]]:2 = hlfir.declare %[[ARG_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !CHECK: %[[C10:.*]] = arith.constant 10 : i32 !CHECK: %[[A_BOX:.*]] = fir.load %[[VAL_1_DECL]]#0 : !fir.ref>> !CHECK: %[[A_ADDR:.*]] = fir.box_addr %[[A_BOX]] : (!fir.box>) -> !fir.ptr diff --git a/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 b/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 index cb26246a6e80f094fdb8367f919b76f6aecf4546..8c1abad8eaa8d51649412cf1d6d2b660ef5811aa 100644 --- a/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 +++ b/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 @@ -6,7 +6,8 @@ ! use_device_ptr to use_device_addr works, without breaking any functionality. !CHECK: func.func @{{.*}}only_use_device_ptr() -!CHECK: omp.target_data use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>>>) use_device_ptr(%{{.*}} -> %{{.*}} : !fir.ref>) { + +!CHECK: omp.target_data use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.llvm_ptr>>) use_device_ptr(%{{.*}} -> %{{.*}} : !fir.ref>) { subroutine only_use_device_ptr use iso_c_binding integer, pointer, dimension(:) :: array @@ -18,7 +19,7 @@ subroutine only_use_device_ptr end subroutine !CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr() -!CHECK: omp.target_data use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>>>) use_device_ptr({{.*}} : !fir.ref>) { +!CHECK: omp.target_data use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.llvm_ptr>>) use_device_ptr({{.*}} : !fir.ref>) { subroutine mix_use_device_ptr_and_addr use iso_c_binding integer, pointer, dimension(:) :: array @@ -30,7 +31,7 @@ subroutine mix_use_device_ptr_and_addr end subroutine !CHECK: func.func @{{.*}}only_use_device_addr() - !CHECK: omp.target_data use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.llvm_ptr>>, !fir.ref>>>, !fir.ref>, !fir.llvm_ptr>>, !fir.ref>>>) { + !CHECK: omp.target_data use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref>>>, !fir.ref>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.llvm_ptr>>) { subroutine only_use_device_addr use iso_c_binding integer, pointer, dimension(:) :: array @@ -42,7 +43,7 @@ subroutine mix_use_device_ptr_and_addr end subroutine !CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr_and_map() - !CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}} : !fir.ref, !fir.ref) use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>>>) use_device_ptr(%{{.*}} : !fir.ref>) { + !CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}} : !fir.ref, !fir.ref) use_device_addr(%{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}}, %{{.*}} -> %{{.*}} : !fir.ref>>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.llvm_ptr>>) use_device_ptr(%{{.*}} : !fir.ref>) { subroutine mix_use_device_ptr_and_addr_and_map use iso_c_binding integer :: i, j @@ -55,7 +56,7 @@ subroutine mix_use_device_ptr_and_addr end subroutine !CHECK: func.func @{{.*}}only_use_map() - !CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !fir.llvm_ptr>>, !fir.ref>>>, !fir.ref>, !fir.llvm_ptr>>, !fir.ref>>>) { + !CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !fir.ref>>>, !fir.ref>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.llvm_ptr>>) { subroutine only_use_map use iso_c_binding integer, pointer, dimension(:) :: array diff --git a/flang/test/Lower/OpenMP/workshare.f90 b/flang/test/Lower/OpenMP/workshare.f90 index 1e11677a15e1f03fc330e0951fe119df0b7fa06f..8e771952f5b6dac28f5ed4f2eab23bd334f26ec8 100644 --- a/flang/test/Lower/OpenMP/workshare.f90 +++ b/flang/test/Lower/OpenMP/workshare.f90 @@ -6,7 +6,7 @@ subroutine sb1(arr) integer :: arr(:) !CHECK: omp.parallel { !$omp parallel -!CHECK: omp.single { +!CHECK: omp.workshare { !$omp workshare arr = 0 !$omp end workshare @@ -20,7 +20,7 @@ subroutine sb2(arr) integer :: arr(:) !CHECK: omp.parallel { !$omp parallel -!CHECK: omp.single nowait { +!CHECK: omp.workshare nowait { !$omp workshare arr = 0 !$omp end workshare nowait @@ -33,7 +33,7 @@ end subroutine subroutine sb3(arr) integer :: arr(:) !CHECK: omp.parallel { -!CHECK: omp.single { +!CHECK: omp.workshare { !$omp parallel workshare arr = 0 !$omp end parallel workshare diff --git a/flang/test/Lower/attributes.f90 b/flang/test/Lower/attributes.f90 index 16e42ab282daeb64c0f20dc1815ce50bc821430e..413024d0a449931c3a43365ad174f970622f6cd9 100644 --- a/flang/test/Lower/attributes.f90 +++ b/flang/test/Lower/attributes.f90 @@ -27,3 +27,11 @@ end subroutine subroutine foo3(x) real, optional, contiguous :: x(:) end subroutine + +! CHECK-LABEL: func @_QPfoo4 +! CHECK-SAME: %arg0: !fir.ref {fir.bindc_name = "x", fir.target} +! CHECK-SAME: %arg1: !fir.ref {fir.asynchronous, fir.bindc_name = "y"} +subroutine foo4(x, y) + real, target :: x + real, asynchronous :: y +end subroutine diff --git a/flang/test/Parser/OpenMP/affinity-clause.f90 b/flang/test/Parser/OpenMP/affinity-clause.f90 index 804723cad7b2b3647576048caaf5e53537724e4c..5e9e0a2194babd8338499b612f96b408f0e1c118 100644 --- a/flang/test/Parser/OpenMP/affinity-clause.f90 +++ b/flang/test/Parser/OpenMP/affinity-clause.f90 @@ -63,7 +63,7 @@ end !PARSE-TREE: OmpBeginBlockDirective !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = task !PARSE-TREE: | OmpClauseList -> OmpClause -> Affinity -> OmpAffinityClause -!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | | TypeDeclarationStmt !PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | | EntityDecl diff --git a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5ba147d20955e33297a2638f6a7e82ea75a43a4f --- /dev/null +++ b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 @@ -0,0 +1,42 @@ +! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s +program main +!CHECK-LABEL: program main + implicit none + + type ty + integer :: x + end type ty + + +!CHECK: !$OMP DECLARE MAPPER (mymapper:ty::mapped) MAP(mapped,mapped%x) + !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x) + +!PARSE-TREE: OpenMPDeclareMapperConstruct +!PARSE-TREE: OmpDeclareMapperSpecifier +!PARSE-TREE: Name = 'mymapper' +!PARSE-TREE: TypeSpec -> DerivedTypeSpec +!PARSE-TREE: Name = 'ty' +!PARSE-TREE: Name = 'mapped' +!PARSE-TREE: OmpMapClause +!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'mapped' +!PARSE-TREE: OmpObject -> Designator -> DataRef -> StructureComponent +!PARSE-TREE: DataRef -> Name = 'mapped' +!PARSE-TREE: Name = 'x' + +!CHECK: !$OMP DECLARE MAPPER (ty::mapped) MAP(mapped,mapped%x) + !$omp declare mapper(ty :: mapped) map(mapped, mapped%x) + +!PARSE-TREE: OpenMPDeclareMapperConstruct +!PARSE-TREE: OmpDeclareMapperSpecifier +!PARSE-TREE: TypeSpec -> DerivedTypeSpec +!PARSE-TREE: Name = 'ty' +!PARSE-TREE: Name = 'mapped' +!PARSE-TREE: OmpMapClause +!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'mapped' +!PARSE-TREE: OmpObject -> Designator -> DataRef -> StructureComponent +!PARSE-TREE: DataRef -> Name = 'mapped' +!PARSE-TREE: Name = 'x' + +end program main +!CHECK-LABEL: end program main diff --git a/flang/test/Parser/OpenMP/defaultmap-clause.f90 b/flang/test/Parser/OpenMP/defaultmap-clause.f90 new file mode 100644 index 0000000000000000000000000000000000000000..6f018ffe8561cdd7980a46ccfff4b71082a1345c --- /dev/null +++ b/flang/test/Parser/OpenMP/defaultmap-clause.f90 @@ -0,0 +1,84 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00 + !$omp target defaultmap(from) + !$omp end target +end + +!UNPARSE: SUBROUTINE f00 +!UNPARSE: !$OMP TARGET DEFAULTMAP(FROM) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = From +!PARSE-TREE: Block + +subroutine f01 + !$omp target defaultmap(firstprivate: aggregate) + !$omp end target +end + +!UNPARSE: SUBROUTINE f01 +!UNPARSE: !$OMP TARGET DEFAULTMAP(FIRSTPRIVATE:AGGREGATE) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Firstprivate +!PARSE-TREE: | | VariableCategory = Aggregate + +subroutine f02 + !$omp target defaultmap(alloc: all) + !$omp end target +end + +!UNPARSE: SUBROUTINE f02 +!UNPARSE: !$OMP TARGET DEFAULTMAP(ALLOC:ALL) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Alloc +!PARSE-TREE: | | VariableCategory = All + +! Both "all" and "allocatable" are valid, and "all" is a prefix of +! "allocatable". Make sure we parse this correctly. +subroutine f03 + !$omp target defaultmap(alloc: allocatable) + !$omp end target +end + +!UNPARSE: SUBROUTINE f03 +!UNPARSE: !$OMP TARGET DEFAULTMAP(ALLOC:ALLOCATABLE) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Alloc +!PARSE-TREE: | | VariableCategory = Allocatable + +subroutine f04 + !$omp target defaultmap(tofrom: scalar) + !$omp end target +end + +!UNPARSE: SUBROUTINE f04 +!UNPARSE: !$OMP TARGET DEFAULTMAP(TOFROM:SCALAR) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Tofrom +!PARSE-TREE: | | VariableCategory = Scalar diff --git a/flang/test/Parser/OpenMP/depobj-construct.f90 b/flang/test/Parser/OpenMP/depobj-construct.f90 index 3de190c95bb734b14f9568032134a5dc759a9ec3..51726a5adf99ec44297a7820ff8548feb245f20a 100644 --- a/flang/test/Parser/OpenMP/depobj-construct.f90 +++ b/flang/test/Parser/OpenMP/depobj-construct.f90 @@ -15,7 +15,7 @@ end !PARSE-TREE: | Verbatim !PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x' !PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> TaskDep -!PARSE-TREE: | | OmpTaskDependenceType -> Type = In +!PARSE-TREE: | | OmpTaskDependenceType -> Value = In !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y' subroutine f01 @@ -31,7 +31,7 @@ end !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct !PARSE-TREE: | Verbatim !PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x' -!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Type = Out +!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Value = Out subroutine f02 integer :: x diff --git a/flang/test/Parser/OpenMP/from-clause.f90 b/flang/test/Parser/OpenMP/from-clause.f90 index 1dcca0b611dfb226f058a4592945a815731d17ed..cff9c077c0a947c28ab758f44566e0888037d816 100644 --- a/flang/test/Parser/OpenMP/from-clause.f90 +++ b/flang/test/Parser/OpenMP/from-clause.f90 @@ -45,7 +45,7 @@ end !PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update !PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause !PARSE-TREE: | Expectation = Present -!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | EntityDecl @@ -74,7 +74,7 @@ end !PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update !PARSE-TREE: OmpClauseList -> OmpClause -> From -> OmpFromClause !PARSE-TREE: | Expectation = Present -!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | EntityDecl diff --git a/flang/test/Parser/OpenMP/in-reduction-clause.f90 b/flang/test/Parser/OpenMP/in-reduction-clause.f90 index 776ead3824b7155982ea802314846a7602569154..ab26ca2d9300fc98313349fd307db4e0f063cb91 100644 --- a/flang/test/Parser/OpenMP/in-reduction-clause.f90 +++ b/flang/test/Parser/OpenMP/in-reduction-clause.f90 @@ -37,14 +37,14 @@ end subroutine omp_in_reduction_taskgroup !PARSE-TREE-NEXT: OmpBeginBlockDirective !PARSE-TREE-NEXT: OmpBlockDirective -> llvm::omp::Directive = task !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause -!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z' !PARSE-TREE: OpenMPConstruct -> OpenMPLoopConstruct !PARSE-TREE-NEXT: OmpBeginLoopDirective !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause -!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PARSE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z' subroutine omp_in_reduction_parallel() @@ -74,6 +74,6 @@ end subroutine omp_in_reduction_parallel !PARSE-TREE-NEXT: OmpBeginLoopDirective !PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop simd !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> InReduction -> OmpInReductionClause -!PARSE-TREE-NEXT: OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PASRE-TREE-NEXT: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'z' diff --git a/flang/test/Parser/OpenMP/map-modifiers.f90 b/flang/test/Parser/OpenMP/map-modifiers.f90 index 0c95f21c5e6a53fff125d225bb9bcd3929d7fedf..578512283c4dcfe066e292c9b8c032bf48327bdc 100644 --- a/flang/test/Parser/OpenMP/map-modifiers.f90 +++ b/flang/test/Parser/OpenMP/map-modifiers.f90 @@ -159,7 +159,7 @@ end !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause !PARSE-TREE: | | TypeModifier = Present -!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | | TypeDeclarationStmt !PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | | EntityDecl @@ -194,7 +194,7 @@ end !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause !PARSE-TREE: | | TypeModifier = Present -!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | | TypeDeclarationStmt !PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | | EntityDecl @@ -229,7 +229,7 @@ end !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause !PARSE-TREE: | | TypeModifier = Present -!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | | TypeDeclarationStmt !PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | | EntityDecl @@ -287,7 +287,7 @@ end !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause !PARSE-TREE: | | TypeModifier = Present -!PARSE-TREE: | | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | | TypeDeclarationStmt !PARSE-TREE: | | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | | EntityDecl @@ -316,3 +316,28 @@ end !PARSE-TREE: | | | | Designator -> DataRef -> Name = 'k' !PARSE-TREE: | | bool = 'true' +subroutine f100(x, y) + integer :: x(10) + integer :: y + integer, parameter :: p = 23 + !$omp target map(mapper(xx), from: x) + x = x + 1 + !$omp end target +end + +!UNPARSE: SUBROUTINE f100 (x, y) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: INTEGER y +!UNPARSE: INTEGER, PARAMETER :: p = 23_4 +!UNPARSE: !$OMP TARGET MAP(MAPPER(XX), FROM: X) +!UNPARSE: x=x+1_4 +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Map -> OmpMapClause +!PARSE-TREE: | | OmpMapperIdentifier -> Name = 'xx' +!PARSE-TREE: | | Type = From +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' + diff --git a/flang/test/Parser/OpenMP/reduction-modifier.f90 b/flang/test/Parser/OpenMP/reduction-modifier.f90 index d46aa709595925c57addc963cdeec445d7f571c4..4bba23bcf061181d92daf7a889bec4404d0611e4 100644 --- a/flang/test/Parser/OpenMP/reduction-modifier.f90 +++ b/flang/test/Parser/OpenMP/reduction-modifier.f90 @@ -10,7 +10,7 @@ subroutine foo() ! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do ! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause ! PARSE-TREE: | | | | | ReductionModifier = Task -! PARSE-TREE: | | | | | OmpReductionOperator -> DefinedOperator -> IntrinsicOperator = Multiply +! PARSE-TREE: | | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply ! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j !$omp do reduction (task, *: j) do i = 1, 10 diff --git a/flang/test/Parser/OpenMP/scan.f90 b/flang/test/Parser/OpenMP/scan.f90 new file mode 100644 index 0000000000000000000000000000000000000000..02fa09b6ef3505727ccf8ba69cdb6f8fa9d114f2 --- /dev/null +++ b/flang/test/Parser/OpenMP/scan.f90 @@ -0,0 +1,58 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +! Check for parsing scan directive +subroutine test_scan(n, a, b) + implicit none + integer n + integer a(n), b(n) + integer x,y,k + + ! a(k) is included in the computation of producing results in b(k) + !$omp parallel do simd reduction(inscan,+: x) + do k = 1, n + x = x + a(k) + !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct + !PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan + !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Inclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' + !CHECK: !$omp scan inclusive(x) + !$omp scan inclusive(x) + b(k) = x + end do + + ! a(k) is not included in the computation of producing results in b(k) + !$omp parallel do simd reduction(inscan,+: x) + do k = 1, n + b(k) = x + !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct + !PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan + !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Exclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' + !CHECK: !$omp scan exclusive(x) + !$omp scan exclusive(x) + x = x + a(k) + end do + + !$omp parallel do simd reduction(inscan,+: x, y) + do k = 1, n + x = x + a(k) + !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct + !PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan + !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Inclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' + !PARSE-TREE-NEXT: OmpObject -> Designator -> DataRef -> Name = 'y' + !CHECK: !$omp scan inclusive(x,y) + !$omp scan inclusive(x, y) + b(k) = x + end do + + !$omp parallel do simd reduction(inscan,+: x, y) + do k = 1, n + x = x + a(k) + !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct + !PARSE-TREE-NEXT: OmpSimpleStandaloneDirective -> llvm::omp::Directive = scan + !PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Exclusive -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' + !PARSE-TREE-NEXT: OmpObject -> Designator -> DataRef -> Name = 'y' + !CHECK: !$omp scan exclusive(x,y) + !$omp scan exclusive(x, y) + b(k) = x + end do +end subroutine diff --git a/flang/test/Parser/OpenMP/target-update-to-clause.f90 b/flang/test/Parser/OpenMP/target-update-to-clause.f90 index 2702575847924b6efbbdfda5088a61087e0e13f1..bb57270fc0bf9cd66ad7eb6d036c64c90ae807f0 100644 --- a/flang/test/Parser/OpenMP/target-update-to-clause.f90 +++ b/flang/test/Parser/OpenMP/target-update-to-clause.f90 @@ -45,7 +45,7 @@ end !PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update !PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause !PARSE-TREE: | Expectation = Present -!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | EntityDecl @@ -74,7 +74,7 @@ end !PARSE-TREE: OmpSimpleStandaloneDirective -> llvm::omp::Directive = target update !PARSE-TREE: OmpClauseList -> OmpClause -> To -> OmpToClause !PARSE-TREE: | Expectation = Present -!PARSE-TREE: | OmpIteratorModifier -> OmpIteratorSpecifier +!PARSE-TREE: | OmpIterator -> OmpIteratorSpecifier !PARSE-TREE: | | TypeDeclarationStmt !PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> !PARSE-TREE: | | | EntityDecl diff --git a/flang/test/Parser/cuf-sanity-common b/flang/test/Parser/cuf-sanity-common index 7005ef07b226507534c44377ad72e26661ce7b43..816e03bed7220a19da6a378148458c1844394fce 100644 --- a/flang/test/Parser/cuf-sanity-common +++ b/flang/test/Parser/cuf-sanity-common @@ -31,6 +31,9 @@ module m !$cuf kernel do <<<1, (2, 3), stream = 1>>> do j = 1, 10 end do + !$cuf kernel do + do j = 1, 10 + end do !$cuf kernel do <<<*, *>>> reduce(+:x,y) reduce(*:z) do j = 1, 10 x = x + a(j) diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90 index b7a3848215930780723b6d6f479c54fe895a2ca7..38b0d090e441d5da466b2c52482afce801a88ae7 100644 --- a/flang/test/Semantics/OpenMP/combined-constructs.f90 +++ b/flang/test/Semantics/OpenMP/combined-constructs.f90 @@ -33,7 +33,7 @@ program main enddo !$omp end target parallel - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target parallel defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -80,7 +80,7 @@ program main enddo !$omp end target parallel do - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target parallel do defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -140,7 +140,7 @@ program main enddo !$omp end target teams - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -240,7 +240,7 @@ program main enddo !$omp end target teams distribute - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams distribute defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -333,7 +333,7 @@ program main enddo !$omp end target teams distribute parallel do - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams distribute parallel do defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -433,7 +433,7 @@ program main enddo !$omp end target teams distribute parallel do simd - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams distribute parallel do simd defaultmap(tofrom) do i = 1, N a(i) = 3.14 diff --git a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 new file mode 100644 index 0000000000000000000000000000000000000000..b4e03bd1632e575bb63b9c11f50954748f6bb5e2 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 @@ -0,0 +1,24 @@ +! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s + +program main +!CHECK-LABEL: MainProgram scope: main + implicit none + + type ty + integer :: x + end type ty + !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x) + !$omp declare mapper(ty :: maptwo) map(maptwo, maptwo%x) + +!! Note, symbols come out in their respective scope, but not in declaration order. +!CHECK: default: Misc ConstructName +!CHECK: mymapper: Misc ConstructName +!CHECK: ty: DerivedType components: x +!CHECK: DerivedType scope: ty +!CHECK: OtherConstruct scope: +!CHECK: mapped (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty) +!CHECK: OtherConstruct scope: +!CHECK: maptwo (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty) + +end program main + diff --git a/flang/test/Semantics/OpenMP/declare-mapper01.f90 b/flang/test/Semantics/OpenMP/declare-mapper01.f90 new file mode 100644 index 0000000000000000000000000000000000000000..0712b80769a45c365bfa57a67ad1c1b0e667d513 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper01.f90 @@ -0,0 +1,8 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! Test the declare mapper with non-derived type. + +integer :: y + +!ERROR: Type is not a derived type +!$omp declare mapper(mm : integer::x) map(x, y) +end diff --git a/flang/test/Semantics/OpenMP/declare-mapper02.f90 b/flang/test/Semantics/OpenMP/declare-mapper02.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a62a7f8d0a392db0f604d7d645ca0bba9aa79ee1 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper02.f90 @@ -0,0 +1,10 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! Test the declare mapper construct with abstract type. + +type, abstract :: t1 + integer :: y +end type t1 + +!ERROR: ABSTRACT derived type may not be used here +!$omp declare mapper(mm : t1::x) map(x, x%y) +end diff --git a/flang/test/Semantics/OpenMP/declare-mapper03.f90 b/flang/test/Semantics/OpenMP/declare-mapper03.f90 new file mode 100644 index 0000000000000000000000000000000000000000..b70b8a67f33e0850b51e15e679c1bc51087e7ef6 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper03.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! Test the declare mapper construct with two default mappers. + +type :: t1 + integer :: y +end type t1 + +type :: t2 + real :: y, z +end type t2 + +!error: 'default' is already declared in this scoping unit + +!$omp declare mapper(t1::x) map(x, x%y) +!$omp declare mapper(t2::w) map(w, w%y, w%z) +end diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a30d90ddce02962180aefa8606ce64bbae9a9584 --- /dev/null +++ b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 @@ -0,0 +1,34 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror + +subroutine f00 +!WARNING: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(tofrom) + !$omp end target +end + +subroutine f01 +!WARNING: AGGREGATE is not allowed in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(tofrom:aggregate) + !$omp end target +end + +subroutine f02 +!WARNING: FROM is not allowed in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(from:scalar) + !$omp end target +end + +subroutine f03 +!WARNING: ALL is not allowed in OpenMP v4.5, try -fopenmp-version=52 + !$omp target defaultmap(tofrom:all) + !$omp end target +end + +subroutine f04 +!WARNING: FROM is not allowed in OpenMP v4.5, try -fopenmp-version=50 +!WARNING: POINTER is not allowed in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(from:pointer) + !$omp end target +end + + diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90 new file mode 100644 index 0000000000000000000000000000000000000000..57bb207bb797a38cd70f4bb0184e7645a39f11e3 --- /dev/null +++ b/flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90 @@ -0,0 +1,23 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 -Werror + +subroutine f00 + !$omp target defaultmap(tofrom) + !$omp end target +end + +subroutine f01 + !$omp target defaultmap(tofrom:aggregate) + !$omp end target +end + +subroutine f02 + !$omp target defaultmap(from:scalar) + !$omp end target +end + +subroutine f03 +!WARNING: ALL is not allowed in OpenMP v5.0, try -fopenmp-version=52 + !$omp target defaultmap(tofrom:all) + !$omp end target +end + diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90 index 4047fbf3fa811d3c7f5fc5cf52c3bbf94a4d08b1..6f545b9021966843c1ef341fff9debb641a30d0e 100644 --- a/flang/test/Semantics/OpenMP/device-constructs.f90 +++ b/flang/test/Semantics/OpenMP/device-constructs.f90 @@ -44,7 +44,6 @@ program main enddo !$omp end target - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause !$omp target defaultmap(tofrom) do i = 1, N a = 3.14 diff --git a/flang/test/Semantics/OpenMP/do05.f90 b/flang/test/Semantics/OpenMP/do05.f90 index c0f240db57b65bdf58c9072763b5d22e0333a708..24844f9fe4f62ac20d8fe2533533891307969816 100644 --- a/flang/test/Semantics/OpenMP/do05.f90 +++ b/flang/test/Semantics/OpenMP/do05.f90 @@ -39,7 +39,7 @@ program omp_do if( i == 5 ) then cycle end if - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region !$omp single do j=1,10 @@ -70,7 +70,7 @@ program omp_do if( i == 3 ) then cycle end if - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region !$omp single do j=1,10 @@ -93,7 +93,7 @@ program omp_do !$omp target parallel do simd do i=1,10 - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region !$omp single do j=1,10 @@ -116,7 +116,7 @@ program omp_do !$omp target teams distribute parallel do simd do i=1,10 - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region !$omp single do j=1,10 diff --git a/flang/test/Semantics/OpenMP/map-clause-symbols.f90 b/flang/test/Semantics/OpenMP/map-clause-symbols.f90 new file mode 100644 index 0000000000000000000000000000000000000000..8f984fcd2fa7e293ff839350429c8a8dd9f0a71d --- /dev/null +++ b/flang/test/Semantics/OpenMP/map-clause-symbols.f90 @@ -0,0 +1,14 @@ +! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s +program main +!CHECK-LABEL: MainProgram scope: main + integer, parameter :: n = 256 + real(8) :: a(256) + !$omp target map(mapper(xx), from:a) + do i=1,n + a(i) = 4.2 + end do + !$omp end target +!CHECK: OtherConstruct scope: size=0 alignment=1 sourceRange=74 bytes +!CHECK: OtherClause scope: size=0 alignment=1 sourceRange=0 bytes +!CHECK: xx: Misc ConstructName +end program main diff --git a/flang/test/Semantics/OpenMP/map-clause.f90 b/flang/test/Semantics/OpenMP/map-clause.f90 index a7430c3edeb949a89eb690ae0004cdb459ea0afb..efcef2571a04a8ead161814fa190e638a346bda5 100644 --- a/flang/test/Semantics/OpenMP/map-clause.f90 +++ b/flang/test/Semantics/OpenMP/map-clause.f90 @@ -33,3 +33,11 @@ subroutine sb(arr) c = 2 !$omp end target end subroutine + +subroutine sb1 + integer :: xx + integer :: a + !ERROR: Name 'xx' should be a mapper name + !$omp target map(mapper(xx), from:a) + !$omp end target +end subroutine sb1 diff --git a/flang/test/Semantics/OpenMP/nested-barrier.f90 b/flang/test/Semantics/OpenMP/nested-barrier.f90 index 7c635d8e23cc0d1df87d3d3b43a3b7cdca2d1bbb..5f51363d59e5937bf9779c33bd07e5e2e4b7b608 100644 --- a/flang/test/Semantics/OpenMP/nested-barrier.f90 +++ b/flang/test/Semantics/OpenMP/nested-barrier.f90 @@ -17,7 +17,7 @@ program omp_nest_barrier !$omp do simd do i = 1, 10 k = k + 1 - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: `BARRIER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`,`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region. !$omp barrier j = j -1 @@ -34,7 +34,7 @@ program omp_nest_barrier !$omp parallel do simd do i = 1, 10 k = k + 1 - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: `BARRIER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`,`CRITICAL`, `ORDERED`, `ATOMIC` or `MASTER` region. !$omp barrier j = j -1 diff --git a/flang/test/Semantics/OpenMP/nested-master.f90 b/flang/test/Semantics/OpenMP/nested-master.f90 index b21ca5d141593186e98d6157051ee42ad8365e07..d51e366eb584bbc921d4484339c87f55c0ac6b52 100644 --- a/flang/test/Semantics/OpenMP/nested-master.f90 +++ b/flang/test/Semantics/OpenMP/nested-master.f90 @@ -64,7 +64,7 @@ program omp_nest_master do i = 1, 10 k = k + 1 !WARNING: OpenMP directive MASTER has been deprecated, please use MASKED instead. - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. !$omp master j = j -1 diff --git a/flang/test/Semantics/OpenMP/nested-simd.f90 b/flang/test/Semantics/OpenMP/nested-simd.f90 index 4149b6d97e9dc7762622d7250fea286ae6fbe352..c9fb90cdeceb252cc408dbba818d8395b94686c6 100644 --- a/flang/test/Semantics/OpenMP/nested-simd.f90 +++ b/flang/test/Semantics/OpenMP/nested-simd.f90 @@ -40,7 +40,7 @@ SUBROUTINE NESTED_BAD(N) !$OMP ORDERED SIMD DO J = 1,N print *, "Hi" - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: TEAMS region can only be strictly nested within the implicit parallel region or TARGET region !$omp teams DO K = 1,N @@ -58,25 +58,25 @@ SUBROUTINE NESTED_BAD(N) !$OMP ATOMIC K = K + 1 IF (I <= 10) THEN - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp task do J = 1, N K = 2 end do !$omp end task - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp target do J = 1, N K = 2 end do !$omp end target - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$OMP DO DO J = 1,N A(J) = J END DO !$OMP END DO - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$OMP PARALLEL DO DO J = 1,N A(J) = J @@ -91,26 +91,26 @@ SUBROUTINE NESTED_BAD(N) !$OMP ATOMIC K = K + 1 IF (I <= 10) THEN - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp task do J = 1, N K = 2 end do !$omp end task - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp target do J = 1, N K = 2 end do !$omp end target - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region !$OMP DO DO J = 1,N A(J) = J END DO !$OMP END DO - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$OMP PARALLEL DO DO J = 1,N A(J) = J @@ -125,26 +125,26 @@ SUBROUTINE NESTED_BAD(N) !$OMP ATOMIC K = K + 1 IF (I <= 10) THEN - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp task do J = 1, N K = 2 end do !$omp end task - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp target do J = 1, N K = 2 end do !$omp end target - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: A worksharing region may not be closely nested inside a worksharing, explicit task, taskloop, critical, ordered, atomic, or master region !$OMP DO DO J = 1,N A(J) = J END DO !$OMP END DO - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$OMP PARALLEL DO DO J = 1,N A(J) = J @@ -159,25 +159,25 @@ SUBROUTINE NESTED_BAD(N) !$OMP ATOMIC K = K + 1 IF (I <= 10) THEN - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp task do J = 1, N K = 2 end do !$omp end task - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$omp target do J = 1, N K = 2 end do !$omp end target - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$OMP DO DO J = 1,N A(J) = J END DO !$OMP END DO - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !$OMP PARALLEL DO DO J = 1,N A(J) = J diff --git a/flang/test/Semantics/OpenMP/ordered-simd.f90 b/flang/test/Semantics/OpenMP/ordered-simd.f90 index 716dc42c28bb644c204ceda22f1c6c5edbff9427..c90ffb3bd1c5ff2f7bdb3e9ab420e5b6a6498f36 100644 --- a/flang/test/Semantics/OpenMP/ordered-simd.f90 +++ b/flang/test/Semantics/OpenMP/ordered-simd.f90 @@ -25,7 +25,7 @@ SUBROUTINE ORDERED_BAD(N) !$OMP DO SIMD DO I = 1,N IF (I <= 10) THEN - !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct, the `SCAN` construct and the `ORDERED` construct with the `SIMD` clause. !ERROR: An ORDERED directive without the DEPEND clause must be closely nested in a worksharing-loop (or worksharing-loop SIMD) region with ORDERED clause without the parameter !$OMP ORDERED CALL WORK(I) diff --git a/flang/test/Semantics/OpenMP/reduction-modifiers.f90 b/flang/test/Semantics/OpenMP/reduction-modifiers.f90 index cf38200ba0a83ea50ddc32057809b5984aa2e5d6..e6238bb8cb7ffcb297241fefb0003270d5733fa9 100644 --- a/flang/test/Semantics/OpenMP/reduction-modifiers.f90 +++ b/flang/test/Semantics/OpenMP/reduction-modifiers.f90 @@ -39,6 +39,7 @@ subroutine mod_inscan1(x) !Correct: worksharing-loop directive !$omp do reduction(inscan, +:x) do i = 1, 100 + !$omp scan inclusive(x) x = foo(i) enddo !$omp end do @@ -50,6 +51,7 @@ subroutine mod_inscan2(x) !Correct: worksharing-loop simd directive !$omp do simd reduction(inscan, +:x) do i = 1, 100 + !$omp scan inclusive(x) x = foo(i) enddo !$omp end do simd @@ -61,6 +63,7 @@ subroutine mod_inscan3(x) !Correct: "simd" directive !$omp simd reduction(inscan, +:x) do i = 1, 100 + !$omp scan inclusive(x) x = foo(i) enddo !$omp end simd @@ -69,7 +72,7 @@ end subroutine mod_inscan4(x) integer, intent(inout) :: x - !ERROR: Modifier 'INSCAN' on REDUCTION clause is only allowed with worksharing-loop, worksharing-loop simd, or SIMD directive + !ERROR: Modifier 'INSCAN' on REDUCTION clause is only allowed with WORKSHARING LOOP, WORKSHARING LOOP SIMD, or SIMD directive !$omp parallel reduction(inscan, +:x) do i = 1, 100 x = foo(i) @@ -80,7 +83,7 @@ end subroutine mod_inscan5(x) integer, intent(inout) :: x - !ERROR: Modifier 'INSCAN' on REDUCTION clause is only allowed with worksharing-loop, worksharing-loop simd, or SIMD directive + !ERROR: Modifier 'INSCAN' on REDUCTION clause is only allowed with WORKSHARING LOOP, WORKSHARING LOOP SIMD, or SIMD directive !$omp sections reduction(inscan, +:x) do i = 1, 100 x = foo(i) diff --git a/flang/test/Semantics/OpenMP/scan1.f90 b/flang/test/Semantics/OpenMP/scan1.f90 new file mode 100644 index 0000000000000000000000000000000000000000..9e8fc9dec1c6bf9cd78bac0249963ad37a2bb36a --- /dev/null +++ b/flang/test/Semantics/OpenMP/scan1.f90 @@ -0,0 +1,34 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp + +subroutine test_scan() + integer x, y, k, z + + !ERROR: Orphaned SCAN directives are prohibited; perhaps you forgot to enclose the directive in to a WORKSHARING LOOP, a WORKSHARING LOOP SIMD or a SIMD directive. + !ERROR: List item x must appear in REDUCTION clause with the INSCAN modifier of the parent directive + !$omp scan inclusive(x) + !$omp parallel do simd + do k = 1, n + !ERROR: UNTIED clause is not allowed on the SCAN directive + !$omp scan untied + end do + + !$omp parallel do simd + do k = 1, n + !ERROR: Exactly one of EXCLUSIVE or INCLUSIVE clause is expected + !$omp scan + end do + +!$omp parallel do simd reduction(inscan,+: x, y) + do k = 1, n + !ERROR: Exactly one of EXCLUSIVE or INCLUSIVE clause is expected + !$omp scan inclusive(x) exclusive(y) + end do + +!ERROR: List item y must appear in EXCLUSIVE or INCLUSIVE clause of an enclosed SCAN directive +!$omp parallel do simd reduction(inscan,+: x, y) + do k = 1, n + !ERROR: Exactly one of EXCLUSIVE or INCLUSIVE clause is expected + !ERROR: List item z must appear in REDUCTION clause with the INSCAN modifier of the parent directive + !$omp scan inclusive(x) exclusive(z) + end do +end subroutine diff --git a/flang/test/Semantics/OpenMP/scan2.f90 b/flang/test/Semantics/OpenMP/scan2.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5232e63aa6b4f15396dc3a6d02256db7fb84310a --- /dev/null +++ b/flang/test/Semantics/OpenMP/scan2.f90 @@ -0,0 +1,27 @@ +! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols -o - %s 2>&1 | FileCheck %s +! Check scan reduction + +! CHECK: MainProgram scope: omp_reduction +program omp_reduction + ! CHECK: i size=4 offset=0: ObjectEntity type: INTEGER(4) + integer i + ! CHECK: k size=4 offset=4: ObjectEntity type: INTEGER(4) init:10_4 + integer :: k = 10 + ! CHECK: m size=4 offset=8: ObjectEntity type: INTEGER(4) init:12_4 + integer :: m = 12 + + ! CHECK: OtherConstruct scope + ! CHECK: i (OmpPrivate, OmpPreDetermined): HostAssoc + ! CHECK: k (OmpReduction, OmpInclusiveScan, OmpInScanReduction): HostAssoc + !$omp parallel do reduction(inscan, +:k) + do i=1,10 + !$omp scan inclusive(k) + end do + !$omp end parallel do + ! CHECK: m (OmpReduction, OmpExclusiveScan, OmpInScanReduction): HostAssoc + !$omp parallel do reduction(inscan, +:m) + do i=1,10 + !$omp scan exclusive(m) + end do + !$omp end parallel do +end program omp_reduction diff --git a/flang/test/Semantics/bind-c17.f90 b/flang/test/Semantics/bind-c17.f90 new file mode 100644 index 0000000000000000000000000000000000000000..8e0ecde67a0a50fbde9612aa7f5215e43765eea4 --- /dev/null +++ b/flang/test/Semantics/bind-c17.f90 @@ -0,0 +1,10 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror +module m + type a ! not BIND(C) + end type + contains + subroutine sub(x) bind(c) + !PORTABILITY: The derived type of this interoperable object should be BIND(C) + type(a), pointer, intent(in) :: x + end +end diff --git a/flang/test/Semantics/bug115674.f90 b/flang/test/Semantics/bug115674.f90 new file mode 100644 index 0000000000000000000000000000000000000000..87c527bb4297a8bd30b39186f2103ac9c1d507df --- /dev/null +++ b/flang/test/Semantics/bug115674.f90 @@ -0,0 +1,9 @@ +!RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s +!CHECK-NOT: error: +program main + sin = 1 + block + intrinsic sin + print *, sin(0.) + end block +end diff --git a/flang/test/Semantics/c_f_pointer.f90 b/flang/test/Semantics/c_f_pointer.f90 index 0cd0161b1fb0064ddce3b2368a90197a25bbaf75..6921438ccded01631f5fb5a371ab16fefd68bd95 100644 --- a/flang/test/Semantics/c_f_pointer.f90 +++ b/flang/test/Semantics/c_f_pointer.f90 @@ -47,7 +47,7 @@ program test call c_f_pointer(scalarC, multiDimIntF, shape=rankTwoArray) !WARNING: FPTR= argument to C_F_POINTER() should not be unlimited polymorphic call c_f_pointer(scalarC, unlimited) - !WARNING: FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C) + !PORTABILITY: FPTR= argument to C_F_POINTER() should not have a derived type that is not BIND(C) call c_f_pointer(scalarC, notBindC) !WARNING: FPTR= argument to C_F_POINTER() should not have the non-interoperable character length CHARACTER(KIND=1,LEN=2_8) call c_f_pointer(scalarC, c2ptr) diff --git a/flang/test/Semantics/call38.f90 b/flang/test/Semantics/call38.f90 index 0e7ebcdfe9df53e64bd159ca85a3a8cb361942e1..34aae6b8b18357b52d9d7fa4468afda5487909ab 100644 --- a/flang/test/Semantics/call38.f90 +++ b/flang/test/Semantics/call38.f90 @@ -522,3 +522,25 @@ module char call scalar('a') end end + +subroutine bug114080(arg, contigArg) + character(*) :: arg(..) + character(*), contiguous :: contigArg(..) + interface + subroutine sub1(arg1) bind(c) + character(1) :: arg1(2,4) + end subroutine + end interface + !ERROR: Assumed-rank character array may not be associated with a dummy argument that is not assumed-rank + call sub1(arg) + !ERROR: Assumed-rank character array may not be associated with a dummy argument that is not assumed-rank + call sub1(contigArg) + !ERROR: Assumed-rank character array may not be associated with a dummy argument that is not assumed-rank + call sub2(arg) + !ERROR: Assumed-rank character array may not be associated with a dummy argument that is not assumed-rank + call sub2(contigArg) + contains + subroutine sub2(arg2) + character(*) :: arg2(10) + end subroutine sub2 +end subroutine diff --git a/flang/test/Semantics/io03.f90 b/flang/test/Semantics/io03.f90 index 9cd672ee01696889c2eb433972a95dbb55d2eff3..6c05924f09dce6af5866ff8dc4c646fc77157488 100644 --- a/flang/test/Semantics/io03.f90 +++ b/flang/test/Semantics/io03.f90 @@ -58,6 +58,13 @@ read(internal_file2, *) jj read(internal_file4, *) jj + !This is a valid statement but it's not what it looks like; "(internal-file)" + !must be parsed as a format expression, not as an internal unit. + read(internal_file) jj + + !ERROR: If UNIT=internal-file appears, FMT or NML must also appear + read(internal_file, iostat=stat1) jj + !ERROR: Internal file must not have a vector subscript read(internal_fileA(vv), *) jj @@ -106,11 +113,12 @@ !ERROR: If UNIT=* appears, POS must not appear read(*, pos=13) + !ERROR: If UNIT=internal-file appears, FMT or NML must also appear !ERROR: If UNIT=internal-file appears, REC must not appear read(internal_file, rec=13) !ERROR: If UNIT=internal-file appears, POS must not appear - read(internal_file, pos=13) + read(internal_file, *, pos=13) !ERROR: If REC appears, END must not appear read(10, fmt='(I4)', end=9, rec=13) jj @@ -135,7 +143,7 @@ read(*, asynchronous='yes') !ERROR: If ASYNCHRONOUS='YES' appears, UNIT=number must also appear - read(internal_file, asynchronous='y'//'es') + read(internal_file, *, asynchronous='y'//'es') !ERROR: If ID appears, ASYNCHRONOUS='YES' must also appear read(10, id=id) diff --git a/flang/test/Semantics/io04.f90 b/flang/test/Semantics/io04.f90 index 685e43dd6e4013bd0ed85cfd5cd20767a478e78c..7114f14a9488a7ad297719c589fedd95c364128c 100644 --- a/flang/test/Semantics/io04.f90 +++ b/flang/test/Semantics/io04.f90 @@ -34,6 +34,7 @@ write(unit=10) 'Ok' write(*, nnn) write(10, nnn) + !ERROR: If UNIT=internal-file appears, FMT or NML must also appear write(internal_file) write(internal_file, *) write(internal_file, fmt=*) @@ -55,7 +56,7 @@ allocate(a(8), stat=stat8) !ERROR: Duplicate UNIT specifier - write(internal_file, unit=*) + write(internal_file, unit=*, fmt=*) !ERROR: WRITE statement must have a UNIT specifier write(nml=nnn) @@ -84,6 +85,7 @@ !ERROR: If UNIT=internal-file appears, POS must not appear write(internal_file, err=9, pos=n, nml=nnn) + !ERROR: If UNIT=internal-file appears, FMT or NML must also appear !ERROR: If UNIT=internal-file appears, REC must not appear write(internal_file, rec=n, err=9) @@ -106,7 +108,7 @@ write(*, asynchronous='yes') !ERROR: If ASYNCHRONOUS='YES' appears, UNIT=number must also appear - write(internal_file, asynchronous='yes') + write(internal_file, *, asynchronous='yes') !ERROR: If ID appears, ASYNCHRONOUS='YES' must also appear write(10, *, id=id) "Ok" diff --git a/flang/test/Semantics/pointer02.f90 b/flang/test/Semantics/pointer02.f90 new file mode 100644 index 0000000000000000000000000000000000000000..90bb43585593957b7cbdfe8619c4cf81b3ab4574 --- /dev/null +++ b/flang/test/Semantics/pointer02.f90 @@ -0,0 +1,53 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +recursive subroutine sub(dp, dpp) + procedure(inner) dp + procedure(inner), pointer :: dpp + procedure(inner) ext + procedure(sub), pointer :: p1 => sub ! ok + procedure(inner), pointer :: p2 => ext ! ok + !ERROR: Procedure pointer 'p3' initializer 'inner' is neither an external nor a module procedure + procedure(inner), pointer :: p3 => inner + !ERROR: Procedure pointer 'p4' initializer 'dp' is neither an external nor a module procedure + procedure(inner), pointer :: p4 => dp + !ERROR: Procedure pointer 'p5' initializer 'dpp' is neither an external nor a module procedure + procedure(inner), pointer :: p5 => dpp + generic :: generic => ext + !ERROR: 'generic' must be an abstract interface or a procedure with an explicit interface + procedure(generic), pointer :: p6 ! => generic + contains + subroutine inner + end +end +recursive function fun() result(res) + procedure(fun), pointer :: p1 => fun ! ok + !ERROR: Procedure pointer 'p2' initializer 'inner' is neither an external nor a module procedure + procedure(inner), pointer :: p2 => inner + res = 0. + contains + function inner() + inner = 0. + end +end +module m + procedure(msub), pointer :: ps1 => msub ! ok + procedure(mfun), pointer :: pf1 => mfun ! ok + contains + recursive subroutine msub + procedure(msub), pointer :: ps2 => msub ! ok + !ERROR: Procedure pointer 'ps3' initializer 'inner' is neither an external nor a module procedure + procedure(inner), pointer :: ps3 => inner + contains + subroutine inner + end + end + recursive function mfun() result(res) + procedure(mfun), pointer :: pf2 => mfun ! ok + !ERROR: Procedure pointer 'pf3' initializer 'inner' is neither an external nor a module procedure + procedure(inner), pointer :: pf3 => inner + res = 0. + contains + function inner() + inner = 0. + end + end +end diff --git a/flang/test/Semantics/smp-def02.f90 b/flang/test/Semantics/smp-def02.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ef27f14edae0a203d6336666f904c9c5e0cec932 --- /dev/null +++ b/flang/test/Semantics/smp-def02.f90 @@ -0,0 +1,42 @@ +!RUN: %flang -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s +!Ensure no bogus error messages about insufficiently defined procedures +!CHECK-NOT: error + +module m + interface + module subroutine smp1(a1) + end + end interface +end + +submodule(m) sm1 + interface + module subroutine smp2(a1,a2) + end + end interface +end + +submodule(m:sm1) sm2 + interface generic + procedure smp1 + procedure smp2 + module subroutine smp3(a1,a2,a3) + end + end interface + contains + subroutine local1 + call generic(0.) + call generic(0., 1.) + call generic(0., 1., 2.) + end + subroutine local2(a1,a2,a3) + end + module procedure smp1 + end + module subroutine smp2(a1,a2) + end + module subroutine smp3(a1,a2,a3) + end +end + + diff --git a/flang/test/Semantics/undef-result01.f90 b/flang/test/Semantics/undef-result01.f90 index 08e7fe1e448998ded55c68e130d29bfa41dc3725..e1ae58dae7c0a693faaa2786c20a4fe56066cb14 100644 --- a/flang/test/Semantics/undef-result01.f90 +++ b/flang/test/Semantics/undef-result01.f90 @@ -117,7 +117,7 @@ function defdByNamelist() end character(4) function defdByWrite() - write(defdByWrite) 'abcd' + write(defdByWrite,*) 'abcd' end integer function defdBySize() diff --git a/flang/test/Transforms/OpenMP/lower-workshare-alloca.mlir b/flang/test/Transforms/OpenMP/lower-workshare-alloca.mlir new file mode 100644 index 0000000000000000000000000000000000000000..12b0558d06ed580d368893e4a4dd4d4c1a112efb --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-alloca.mlir @@ -0,0 +1,53 @@ +// RUN: fir-opt --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + +// Checks that fir.alloca is hoisted out and copyprivate'd +func.func @wsfunc() { + omp.workshare { + %c1 = arith.constant 1 : index + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %alloc = fir.alloca i32 + fir.store %c1_i32 to %alloc : !fir.ref + omp.workshare.loop_wrapper { + omp.loop_nest (%arg1) : index = (%c1) to (%c42) inclusive step (%c1) { + "test.test1"(%alloc) : (!fir.ref) -> () + omp.yield + } + } + "test.test2"(%alloc) : (!fir.ref) -> () + omp.terminator + } + return +} + +// CHECK-LABEL: func.func private @_workshare_copy_i32( +// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref, +// CHECK-SAME: %[[VAL_1:.*]]: !fir.ref) { +// CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1]] : !fir.ref +// CHECK: fir.store %[[VAL_2]] to %[[VAL_0]] : !fir.ref +// CHECK: return +// CHECK: } + +// CHECK-LABEL: func.func @wsfunc() { +// CHECK: %[[VAL_0:.*]] = fir.alloca i32 +// CHECK: omp.single copyprivate(%[[VAL_0]] -> @_workshare_copy_i32 : !fir.ref) { +// CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 +// CHECK: fir.store %[[VAL_1]] to %[[VAL_0]] : !fir.ref +// CHECK: omp.terminator +// CHECK: } +// CHECK: %[[VAL_2:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_3:.*]] = arith.constant 42 : index +// CHECK: omp.wsloop { +// CHECK: omp.loop_nest (%[[VAL_4:.*]]) : index = (%[[VAL_2]]) to (%[[VAL_3]]) inclusive step (%[[VAL_2]]) { +// CHECK: "test.test1"(%[[VAL_0]]) : (!fir.ref) -> () +// CHECK: omp.yield +// CHECK: } +// CHECK: } +// CHECK: omp.single nowait { +// CHECK: "test.test2"(%[[VAL_0]]) : (!fir.ref) -> () +// CHECK: omp.terminator +// CHECK: } +// CHECK: omp.barrier +// CHECK: return +// CHECK: } + diff --git a/flang/test/Transforms/OpenMP/lower-workshare-binding.mlir b/flang/test/Transforms/OpenMP/lower-workshare-binding.mlir new file mode 100644 index 0000000000000000000000000000000000000000..f1d0e8e2296140a040862f3b2d143b6ab7f443ec --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-binding.mlir @@ -0,0 +1,49 @@ +// RUN: fir-opt --split-input-file --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + +// Checks that the omp.workshare.loop_wrapper binds to the correct omp.workshare + +func.func @wsfunc() { + %c1 = arith.constant 1 : index + %c42 = arith.constant 42 : index + omp.parallel { + omp.workshare nowait { + omp.parallel { + omp.workshare nowait { + omp.workshare.loop_wrapper { + omp.loop_nest (%arg1) : index = (%c1) to (%c42) inclusive step (%c1) { + "test.test2"() : () -> () + omp.yield + } + } + omp.terminator + } + omp.terminator + } + omp.terminator + } + omp.terminator + } + return +} + +// CHECK-LABEL: func.func @wsfunc() { +// CHECK: %[[VAL_0:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_1:.*]] = arith.constant 42 : index +// CHECK: omp.parallel { +// CHECK: omp.single nowait { +// CHECK: omp.parallel { +// CHECK: omp.wsloop nowait { +// CHECK: omp.loop_nest (%[[VAL_2:.*]]) : index = (%[[VAL_0]]) to (%[[VAL_1]]) inclusive step (%[[VAL_0]]) { +// CHECK: "test.test2"() : () -> () +// CHECK: omp.yield +// CHECK: } +// CHECK: } +// CHECK: omp.terminator +// CHECK: } +// CHECK: omp.terminator +// CHECK: } +// CHECK: omp.terminator +// CHECK: } +// CHECK: return +// CHECK: } + diff --git a/flang/test/Transforms/OpenMP/lower-workshare-cleanup.mlir b/flang/test/Transforms/OpenMP/lower-workshare-cleanup.mlir new file mode 100644 index 0000000000000000000000000000000000000000..ca288917a3ac492f87bd07469201a0f0bfcbc25c --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-cleanup.mlir @@ -0,0 +1,57 @@ +// RUN: fir-opt --split-input-file --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + +// Check that we cleanup unused pure operations from the parallel and single +// regions + +// CHECK-LABEL: func.func @wsfunc() { +// CHECK: %[[VAL_0:.*]] = fir.alloca i32 +// CHECK: omp.parallel { +// CHECK: omp.single { +// CHECK: %[[VAL_1:.*]] = "test.test1"() : () -> i32 +// CHECK: %[[VAL_2:.*]] = arith.constant 2 : index +// CHECK: %[[VAL_3:.*]] = arith.constant 3 : index +// CHECK: %[[VAL_4:.*]] = arith.addi %[[VAL_2]], %[[VAL_3]] : index +// CHECK: "test.test3"(%[[VAL_4]]) : (index) -> () +// CHECK: omp.terminator +// CHECK: } +// CHECK: %[[VAL_5:.*]] = arith.constant 1 : index +// CHECK: %[[VAL_6:.*]] = arith.constant 42 : index +// CHECK: omp.wsloop nowait { +// CHECK: omp.loop_nest (%[[VAL_7:.*]]) : index = (%[[VAL_5]]) to (%[[VAL_6]]) inclusive step (%[[VAL_5]]) { +// CHECK: "test.test2"() : () -> () +// CHECK: omp.yield +// CHECK: } +// CHECK: } +// CHECK: omp.barrier +// CHECK: omp.terminator +// CHECK: } +// CHECK: return +// CHECK: } +func.func @wsfunc() { + %a = fir.alloca i32 + omp.parallel { + omp.workshare { + %t1 = "test.test1"() : () -> i32 + + %c1 = arith.constant 1 : index + %c42 = arith.constant 42 : index + + %c2 = arith.constant 2 : index + %c3 = arith.constant 3 : index + %add = arith.addi %c2, %c3 : index + "test.test3"(%add) : (index) -> () + + omp.workshare.loop_wrapper { + omp.loop_nest (%arg1) : index = (%c1) to (%c42) inclusive step (%c1) { + "test.test2"() : () -> () + omp.yield + } + } + omp.terminator + } + omp.terminator + } + return +} + + diff --git a/flang/test/Transforms/OpenMP/lower-workshare-copyprivate.mlir b/flang/test/Transforms/OpenMP/lower-workshare-copyprivate.mlir new file mode 100644 index 0000000000000000000000000000000000000000..d7a04e198ceed93fa9923ff862bdb1c20fa730db --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-copyprivate.mlir @@ -0,0 +1,73 @@ +// RUN: fir-opt --split-input-file --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + + +// Check if we store the correct values + +func.func @wsfunc() { + omp.parallel { + // CHECK: fir.alloca + // CHECK: fir.alloca + // CHECK: fir.alloca + // CHECK: fir.alloca + // CHECK: fir.alloca + // CHECK-NOT: fir.alloca + omp.workshare { + + %t1 = "test.test1"() : () -> i32 + // CHECK: %[[T1:.*]] = "test.test1" + // CHECK: fir.store %[[T1]] + %t2 = "test.test2"() : () -> i32 + // CHECK: %[[T2:.*]] = "test.test2" + // CHECK: fir.store %[[T2]] + %t3 = "test.test3"() : () -> i32 + // CHECK: %[[T3:.*]] = "test.test3" + // CHECK-NOT: fir.store %[[T3]] + %t4 = "test.test4"() : () -> i32 + // CHECK: %[[T4:.*]] = "test.test4" + // CHECK: fir.store %[[T4]] + %t5 = "test.test5"() : () -> i32 + // CHECK: %[[T5:.*]] = "test.test5" + // CHECK: fir.store %[[T5]] + %t6 = "test.test6"() : () -> i32 + // CHECK: %[[T6:.*]] = "test.test6" + // CHECK-NOT: fir.store %[[T6]] + + + "test.test1"(%t1) : (i32) -> () + "test.test1"(%t2) : (i32) -> () + "test.test1"(%t3) : (i32) -> () + + %true = arith.constant true + fir.if %true { + "test.test2"(%t3) : (i32) -> () + } + + %c1_i32 = arith.constant 1 : i32 + + %t5_pure_use = arith.addi %t5, %c1_i32 : i32 + + %t6_mem_effect_use = "test.test8"(%t6) : (i32) -> i32 + // CHECK: %[[T6_USE:.*]] = "test.test8" + // CHECK: fir.store %[[T6_USE]] + + %c42 = arith.constant 42 : index + %c1 = arith.constant 1 : index + omp.workshare.loop_wrapper { + omp.loop_nest (%arg1) : index = (%c1) to (%c42) inclusive step (%c1) { + "test.test10"(%t1) : (i32) -> () + "test.test10"(%t5_pure_use) : (i32) -> () + "test.test10"(%t6_mem_effect_use) : (i32) -> () + omp.yield + } + } + + "test.test10"(%t2) : (i32) -> () + fir.if %true { + "test.test10"(%t4) : (i32) -> () + } + omp.terminator + } + omp.terminator + } + return +} diff --git a/flang/test/Transforms/OpenMP/lower-workshare-correct-parallelize.mlir b/flang/test/Transforms/OpenMP/lower-workshare-correct-parallelize.mlir new file mode 100644 index 0000000000000000000000000000000000000000..31db8213b5f001a63c36d8d8469177a5faba5f3e --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-correct-parallelize.mlir @@ -0,0 +1,25 @@ +// RUN: fir-opt --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + +// Check that the safe to parallelize `fir.declare` op will not be parallelized +// due to its operand %alloc not being reloaded outside the omp.single. + +func.func @foo() { + %c0 = arith.constant 0 : index + omp.workshare { + %alloc = fir.allocmem !fir.array, %c0 {bindc_name = ".tmp.forall", uniq_name = ""} + %shape = fir.shape %c0 : (index) -> !fir.shape<1> + %declare = fir.declare %alloc(%shape) {uniq_name = ".tmp.forall"} : (!fir.heap>, !fir.shape<1>) -> !fir.heap> + fir.freemem %alloc : !fir.heap> + omp.terminator + } + return +} + +// CHECK: omp.single nowait +// CHECK: fir.allocmem +// CHECK: fir.shape +// CHECK: fir.declare +// CHECK: fir.freemem +// CHECK: omp.terminator +// CHECK: } +// CHECK: omp.barrier diff --git a/flang/test/Transforms/OpenMP/lower-workshare-no-single.mlir b/flang/test/Transforms/OpenMP/lower-workshare-no-single.mlir new file mode 100644 index 0000000000000000000000000000000000000000..1fd379a6e5eb4870605055314ee8a5f34829e781 --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-no-single.mlir @@ -0,0 +1,19 @@ +// RUN: fir-opt --split-input-file --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + +// Check that we do not emit an omp.single for the constant operation + +func.func @foo() { + omp.workshare { + %c1 = arith.constant 1 : index + omp.workshare.loop_wrapper { + omp.loop_nest (%arg1) : index = (%c1) to (%c1) inclusive step (%c1) { + "test.test0"() : () -> () + omp.yield + } + } + omp.terminator + } + return +} + +// CHECK-NOT: omp.single diff --git a/flang/test/Transforms/OpenMP/lower-workshare-nowait.mlir b/flang/test/Transforms/OpenMP/lower-workshare-nowait.mlir new file mode 100644 index 0000000000000000000000000000000000000000..940662e0bdccc2ad29d23b7de8949415b32191bc --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-nowait.mlir @@ -0,0 +1,23 @@ +// RUN: fir-opt --split-input-file --lower-workshare --allow-unregistered-dialect %s | FileCheck %s + +// Check that we correctly handle nowait + +// CHECK-LABEL: func.func @nonowait +func.func @nonowait(%arg0: !fir.ref>) { + // CHECK: omp.barrier + omp.workshare { + omp.terminator + } + return +} + +// ----- + +// CHECK-LABEL: func.func @nowait +func.func @nowait(%arg0: !fir.ref>) { + // CHECK-NOT: omp.barrier + omp.workshare nowait { + omp.terminator + } + return +} diff --git a/flang/test/Transforms/OpenMP/lower-workshare-todo-cfg-dom.mlir b/flang/test/Transforms/OpenMP/lower-workshare-todo-cfg-dom.mlir new file mode 100644 index 0000000000000000000000000000000000000000..83c49cd635d082a2cfc42fdf0afb0b22bd45ee72 --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-todo-cfg-dom.mlir @@ -0,0 +1,26 @@ +// RUN: fir-opt --lower-workshare --allow-unregistered-dialect %s 2>&1 | FileCheck %s + +// CHECK: warning: omp workshare with unstructured control flow is currently unsupported and will be serialized. + +// CHECK: omp.parallel +// CHECK-NEXT: omp.single + +// TODO Check that the definition of %r dominates its use post-transform +func.func @wsfunc() { + %a = fir.alloca i32 + omp.parallel { + omp.workshare { + ^bb1: + %c1 = arith.constant 1 : i32 + cf.br ^bb3(%c1: i32) + ^bb2: + "test.test2"(%r) : (i32) -> () + omp.terminator + ^bb3(%arg1: i32): + %r = "test.test2"(%arg1) : (i32) -> i32 + cf.br ^bb2 + } + omp.terminator + } + return +} diff --git a/flang/test/Transforms/OpenMP/lower-workshare-todo-cfg.mlir b/flang/test/Transforms/OpenMP/lower-workshare-todo-cfg.mlir new file mode 100644 index 0000000000000000000000000000000000000000..a27cf88069401486a8339db2e23c40b9e7c19c06 --- /dev/null +++ b/flang/test/Transforms/OpenMP/lower-workshare-todo-cfg.mlir @@ -0,0 +1,23 @@ +// RUN: fir-opt --lower-workshare --allow-unregistered-dialect %s 2>&1 | FileCheck %s + +// CHECK: warning: omp workshare with unstructured control flow is currently unsupported and will be serialized. + +// CHECK: omp.parallel +// CHECK-NEXT: omp.single + +// TODO Check transforming a simple CFG +func.func @wsfunc() { + %a = fir.alloca i32 + omp.parallel { + omp.workshare { + ^bb1: + %c1 = arith.constant 1 : i32 + cf.br ^bb3(%c1: i32) + ^bb3(%arg1: i32): + "test.test2"(%arg1) : (i32) -> () + omp.terminator + } + omp.terminator + } + return +} diff --git a/flang/test/Transforms/OpenMP/should-use-workshare-lowering.mlir b/flang/test/Transforms/OpenMP/should-use-workshare-lowering.mlir new file mode 100644 index 0000000000000000000000000000000000000000..91b08123cce422aae49ef1a6b82c0766bb08fa00 --- /dev/null +++ b/flang/test/Transforms/OpenMP/should-use-workshare-lowering.mlir @@ -0,0 +1,162 @@ +// RUN: fir-opt --bufferize-hlfir %s | FileCheck %s + +// Checks that we correctly identify when to use the lowering to +// omp.workshare.loop_wrapper + +// CHECK-LABEL: @should_parallelize_0 +// CHECK: omp.workshare.loop_wrapper +func.func @should_parallelize_0(%arg: !fir.ref>, %idx : index) { + omp.workshare { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + return +} + +// CHECK-LABEL: @should_parallelize_1 +// CHECK: omp.workshare.loop_wrapper +func.func @should_parallelize_1(%arg: !fir.ref>, %idx : index) { + omp.parallel { + omp.workshare { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + omp.terminator + } + return +} + + +// CHECK-LABEL: @should_not_parallelize_0 +// CHECK-NOT: omp.workshare.loop_wrapper +func.func @should_not_parallelize_0(%arg: !fir.ref>, %idx : index) { + omp.workshare { + omp.single { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + omp.terminator + } + return +} + +// CHECK-LABEL: @should_not_parallelize_1 +// CHECK-NOT: omp.workshare.loop_wrapper +func.func @should_not_parallelize_1(%arg: !fir.ref>, %idx : index) { + omp.workshare { + omp.critical { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + omp.terminator + } + return +} + +// CHECK-LABEL: @should_not_parallelize_2 +// CHECK-NOT: omp.workshare.loop_wrapper +func.func @should_not_parallelize_2(%arg: !fir.ref>, %idx : index) { + omp.workshare { + omp.parallel { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + omp.terminator + } + return +} + +// CHECK-LABEL: @should_not_parallelize_3 +// CHECK-NOT: omp.workshare.loop_wrapper +func.func @should_not_parallelize_3(%arg: !fir.ref>, %idx : index) { + omp.workshare { + omp.parallel { + omp.workshare { + omp.parallel { + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + omp.terminator + } + omp.terminator + } + omp.terminator + } + omp.terminator + } + return +} + +// CHECK-LABEL: @should_not_parallelize_4 +// CHECK-NOT: omp.workshare.loop_wrapper +func.func @should_not_parallelize_4(%arg: !fir.ref>, %idx : index) { + omp.workshare { + ^bb1: + %c42 = arith.constant 42 : index + %c1_i32 = arith.constant 1 : i32 + %shape = fir.shape %c42 : (index) -> !fir.shape<1> + %array:2 = hlfir.declare %arg(%shape) {uniq_name = "array"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) + %elemental = hlfir.elemental %shape unordered : (!fir.shape<1>) -> !hlfir.expr<42xi32> { + ^bb0(%i: index): + hlfir.yield_element %c1_i32 : i32 + } + hlfir.assign %elemental to %array#0 : !hlfir.expr<42xi32>, !fir.ref> + hlfir.destroy %elemental : !hlfir.expr<42xi32> + cf.br ^bb2 + ^bb2: + omp.terminator + } + return +} diff --git a/flang/test/Transforms/debug-class-type.fir b/flang/test/Transforms/debug-class-type.fir new file mode 100644 index 0000000000000000000000000000000000000000..aad15a831fd2fa98dd37e52542188b9957d835ca --- /dev/null +++ b/flang/test/Transforms/debug-class-type.fir @@ -0,0 +1,34 @@ +// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s + +module attributes {dlti.dl_spec = #dlti.dl_spec<>} { + fir.type_info @_QTtest_type nofinal : !fir.type<_QTtest_type{a:i32,b:!fir.box>>}> dispatch_table { + fir.dt_entry "test_proc", @_QPtest_proc + } loc(#loc1) + func.func private @_QPtest_proc(%arg0: !fir.class>>}>>) + + func.func @test() { + %0 = fir.address_of(@_QFEx) : !fir.ref>>}>>>> + %1 = fircg.ext_declare %0 {uniq_name = "_QFEx"} : (!fir.ref>>}>>>>) -> !fir.ref>>}>>>> loc(#loc3) + %2 = fir.address_of(@_QFEy) : !fir.ref>>}>>>> + %3 = fircg.ext_declare %2 {uniq_name = "_QFEy"} : (!fir.ref>>}>>>>) -> !fir.ref>>}>>>> loc(#loc4) + %4 = fir.address_of(@_QFEz) : !fir.ref> + %5 = fircg.ext_declare %4 {uniq_name = "_QFEz"} : (!fir.ref>) -> !fir.ref> loc(#loc4) + %6 = fir.address_of(@_QFEt) : !fir.ref>> + %7 = fircg.ext_declare %6 {uniq_name = "_QFEt"} : (!fir.ref>>) -> !fir.ref>> loc(#loc4) + return + } loc(#loc2) +} + +#loc1 = loc("./simple.f90":2:1) +#loc2 = loc("./simple.f90":10:1) +#loc3 = loc("./simple.f90":15:1) +#loc4 = loc("./simple.f90":22:1) + +// CHECK-DAG: #[[TY1:.*]] = #llvm.di_composite_type<{{.*}}name = "test_type"{{.*}}> +// CHECK-DAG: #[[TY2:.*]] = #llvm.di_derived_type +// CHECK-DAG: #[[TY3:.*]] = #llvm.di_derived_type +// CHECK-DAG: #llvm.di_subroutine_type +// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "x"{{.*}}type = #[[TY2]]> +// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "y"{{.*}}type = #[[TY2]]> +// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "z"{{.*}}type = #[[TY3]]> +// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "t"{{.*}}type = #[[TY3]]> diff --git a/flang/test/Transforms/omp-map-info-finalization.fir b/flang/test/Transforms/omp-map-info-finalization.fir index fa7b65d41929b73d4bb514498702038ff4a08030..74b87152d5b0543e59a39c88e7b6a0dfd4a728ca 100644 --- a/flang/test/Transforms/omp-map-info-finalization.fir +++ b/flang/test/Transforms/omp-map-info-finalization.fir @@ -1,31 +1,29 @@ // RUN: fir-opt --split-input-file --omp-map-info-finalization %s | FileCheck %s -module attributes {omp.is_target_device = false} { - func.func @test_descriptor_expansion_pass(%arg0: !fir.box>) { - %0 = fir.alloca !fir.box> - %1 = fir.zero_bits !fir.heap - %2:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs, uniq_name = "test"} : (!fir.box>) -> (!fir.box>, !fir.box>) - %3 = fir.embox %1 : (!fir.heap) -> !fir.box> - fir.store %3 to %0 : !fir.ref>> - %4:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "test2"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) - %5 = fir.allocmem i32 {fir.must_be_heap = true} - %6 = fir.embox %5 : (!fir.heap) -> !fir.box> - fir.store %6 to %4#1 : !fir.ref>> - %c0 = arith.constant 1 : index - %c1 = arith.constant 0 : index - %c2 = arith.constant 10 : index - %dims:3 = fir.box_dims %2#1, %c1 : (!fir.box>, index) -> (index, index, index) - %bounds = omp.map.bounds lower_bound(%c1 : index) upper_bound(%c2 : index) extent(%dims#1 : index) stride(%dims#2 : index) start_idx(%c0 : index) {stride_in_bytes = true} - %7 = fir.box_addr %2#1 : (!fir.box>) -> !fir.ref> - %8 = omp.map.info var_ptr(%4#1 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) -> !fir.ref>> - %9 = omp.map.info var_ptr(%7 : !fir.ref>, !fir.array) map_clauses(from) capture(ByRef) bounds(%bounds) -> !fir.ref> - omp.target map_entries(%8 -> %arg1, %9 -> %arg2 : !fir.ref>>, !fir.ref>) { - omp.terminator - } - return +func.func @test_descriptor_expansion_pass(%arg0: !fir.box>) { + %0 = fir.alloca !fir.box> + %1 = fir.zero_bits !fir.heap + %2:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs, uniq_name = "test"} : (!fir.box>) -> (!fir.box>, !fir.box>) + %3 = fir.embox %1 : (!fir.heap) -> !fir.box> + fir.store %3 to %0 : !fir.ref>> + %4:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "test2"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) + %5 = fir.allocmem i32 {fir.must_be_heap = true} + %6 = fir.embox %5 : (!fir.heap) -> !fir.box> + fir.store %6 to %4#1 : !fir.ref>> + %c0 = arith.constant 1 : index + %c1 = arith.constant 0 : index + %c2 = arith.constant 10 : index + %dims:3 = fir.box_dims %2#1, %c1 : (!fir.box>, index) -> (index, index, index) + %bounds = omp.map.bounds lower_bound(%c1 : index) upper_bound(%c2 : index) extent(%dims#1 : index) stride(%dims#2 : index) start_idx(%c0 : index) {stride_in_bytes = true} + %7 = fir.box_addr %2#1 : (!fir.box>) -> !fir.ref> + %8 = omp.map.info var_ptr(%4#1 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) -> !fir.ref>> + %9 = omp.map.info var_ptr(%7 : !fir.ref>, !fir.array) map_clauses(from) capture(ByRef) bounds(%bounds) -> !fir.ref> + omp.target map_entries(%8 -> %arg1, %9 -> %arg2 : !fir.ref>>, !fir.ref>) { + omp.terminator } + return } - + // CHECK: func.func @test_descriptor_expansion_pass(%[[ARG0:.*]]: !fir.box>) { // CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.box> // CHECK: %[[ALLOCA2:.*]] = fir.alloca !fir.box> @@ -34,60 +32,267 @@ module attributes {omp.is_target_device = false} { // CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} // CHECK: %[[BASE_ADDR_OFF:.*]] = fir.box_offset %[[DECLARE2]]#1 base_addr : (!fir.ref>>) -> !fir.llvm_ptr> // CHECK: %[[DESC_MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref>>, i32) var_ptr_ptr(%[[BASE_ADDR_OFF]] : !fir.llvm_ptr>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr> {name = ""} -// CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref>>, !fir.box>) map_clauses(tofrom) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> +// CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : [0] : !fir.llvm_ptr>) -> !fir.ref>> // CHECK: fir.store %[[DECLARE1]]#1 to %[[ALLOCA]] : !fir.ref>> // CHECK: %[[BASE_ADDR_OFF_2:.*]] = fir.box_offset %[[ALLOCA]] base_addr : (!fir.ref>>) -> !fir.llvm_ptr>> // CHECK: %[[DESC_MEMBER_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref>>, !fir.array) var_ptr_ptr(%[[BASE_ADDR_OFF_2]] : !fir.llvm_ptr>>) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {name = ""} -// CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref>>, !fir.box>) map_clauses(from) capture(ByRef) members(%[[DESC_MEMBER_MAP_2]] : [0] : !fir.llvm_ptr>>) -> !fir.ref> -// CHECK: omp.target map_entries(%[[DESC_MEMBER_MAP]] -> %[[ARG1:.*]], %[[DESC_PARENT_MAP]] -> %[[ARG2:.*]], %[[DESC_MEMBER_MAP_2]] -> %[[ARG3:.*]], %[[DESC_PARENT_MAP_2]] -> %[[ARG4:.*]] : {{.*}}) { +// CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref>>, !fir.box>) map_clauses(to) capture(ByRef) members(%[[DESC_MEMBER_MAP_2]] : [0] : !fir.llvm_ptr>>) -> !fir.ref> +// CHECK: omp.target map_entries(%[[DESC_PARENT_MAP]] -> %[[ARG1:.*]], %[[DESC_PARENT_MAP_2]] -> %[[ARG2:.*]], %[[DESC_MEMBER_MAP]] -> %[[ARG3:.*]], %[[DESC_MEMBER_MAP_2]] -> %[[ARG4:.*]] : {{.*}}) { // ----- -module attributes {omp.is_target_device = false} { - func.func @test_derived_type_map_operand_and_block_addition(%arg0: !fir.ref,nested:!fir.box>>,ry:f32}>>) { - %0 = hlfir.designate %arg0{"rx"} : (!fir.ref,nested:!fir.box>>,ry:f32}>>) -> !fir.ref - %1 = omp.map.info var_ptr(%0 : !fir.ref, f32) map_clauses(from) capture(ByRef) -> !fir.ref {name = "scalar_struct%rx"} - %2 = hlfir.designate %arg0{"ry"} : (!fir.ref,nested:!fir.box>>,ry:f32}>>) -> !fir.ref - %3 = omp.map.info var_ptr(%2 : !fir.ref, f32) map_clauses(from) capture(ByRef) -> !fir.ref {name = "scalar_struct%ry"} - %4 = omp.map.info var_ptr(%arg0 : !fir.ref,nested:!fir.box>>,ry:f32}>>, !fir.type<_QFTdtype{ix:i32,rx:f32,zx:complex,nested:!fir.box>>,ry:f32}>) map_clauses(from) capture(ByRef) members(%1, %3 : [1], [4] : !fir.ref, !fir.ref) -> !fir.ref,nested:!fir.box>>,ry:f32}>> {name = "scalar_struct", partial_map = true} - omp.target map_entries(%4 -> %arg1 : !fir.ref,nested:!fir.box>>,ry:f32}>>) { - omp.terminator - } - return +func.func @test_derived_type_map_operand_and_block_addition(%arg0: !fir.ref,nested:!fir.box>>,ry:f32}>>) { + %0 = hlfir.designate %arg0{"rx"} : (!fir.ref,nested:!fir.box>>,ry:f32}>>) -> !fir.ref + %1 = omp.map.info var_ptr(%0 : !fir.ref, f32) map_clauses(from) capture(ByRef) -> !fir.ref {name = "scalar_struct%rx"} + %2 = hlfir.designate %arg0{"ry"} : (!fir.ref,nested:!fir.box>>,ry:f32}>>) -> !fir.ref + %3 = omp.map.info var_ptr(%2 : !fir.ref, f32) map_clauses(from) capture(ByRef) -> !fir.ref {name = "scalar_struct%ry"} + %4 = omp.map.info var_ptr(%arg0 : !fir.ref,nested:!fir.box>>,ry:f32}>>, !fir.type<_QFTdtype{ix:i32,rx:f32,zx:complex,nested:!fir.box>>,ry:f32}>) map_clauses(from) capture(ByRef) members(%1, %3 : [1], [4] : !fir.ref, !fir.ref) -> !fir.ref,nested:!fir.box>>,ry:f32}>> {name = "scalar_struct", partial_map = true} + omp.target map_entries(%4 -> %arg1 : !fir.ref,nested:!fir.box>>,ry:f32}>>) { + omp.terminator } + return } // CHECK: func.func @test_derived_type_map_operand_and_block_addition(%{{.*}}: !fir.ref,nested:!fir.box>>,ry:f32}>>) { // CHECK: %[[MAP_MEMBER_1:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref, f32) map_clauses(from) capture(ByRef) -> !fir.ref {name = "scalar_struct%rx"} // CHECK: %[[MAP_MEMBER_2:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref, f32) map_clauses(from) capture(ByRef) -> !fir.ref {name = "scalar_struct%ry"} // CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref,nested:!fir.box>>,ry:f32}>>, !fir.type<_QFTdtype{ix:i32,rx:f32,zx:complex,nested:!fir.box>>,ry:f32}>) map_clauses(from) capture(ByRef) members(%[[MAP_MEMBER_1]], %[[MAP_MEMBER_2]] : [1], [4] : !fir.ref, !fir.ref) -> !fir.ref,nested:!fir.box>>,ry:f32}>> {name = "scalar_struct", partial_map = true} -// CHECK: omp.target map_entries(%[[MAP_MEMBER_1]] -> %[[ARG1:.*]], %[[MAP_MEMBER_2]] -> %[[ARG2:.*]], %[[MAP_PARENT]] -> %[[ARG3:.*]] : !fir.ref, !fir.ref, !fir.ref,nested:!fir.box>>,ry:f32}>>) { +// CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG1:.*]], %[[MAP_MEMBER_1]] -> %[[ARG2:.*]], %[[MAP_MEMBER_2]] -> %[[ARG3:.*]] : !fir.ref,nested:!fir.box>>,ry:f32}>>, !fir.ref, !fir.ref) { // ----- -module attributes {omp.is_target_device = false} { func.func @test_nested_derived_type_map_operand_and_block_addition(%arg0: !fir.ref}>>) { - %0 = fir.declare %arg0 {uniq_name = "_QFmaptype_derived_nested_explicit_multiple_membersEsa"} : (!fir.ref}>>) -> !fir.ref}>> - %1 = fir.field_index n, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTscalar_and_array{r:f32,n:!fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}>}> - %2 = fir.coordinate_of %0, %1 : (!fir.ref}>>, !fir.field) -> !fir.ref> - %3 = fir.field_index i, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}> - %4 = fir.coordinate_of %2, %3 : (!fir.ref>, !fir.field) -> !fir.ref - %5 = omp.map.info var_ptr(%4 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "sa%n%i"} - %6 = fir.field_index n, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTscalar_and_array{r:f32,n:!fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}>}> - %7 = fir.coordinate_of %0, %6 : (!fir.ref}>>, !fir.field) -> !fir.ref> - %8 = fir.field_index r, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}> - %9 = fir.coordinate_of %7, %8 : (!fir.ref>, !fir.field) -> !fir.ref - %10 = omp.map.info var_ptr(%9 : !fir.ref, f32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "sa%n%r"} - %11 = omp.map.info var_ptr(%0 : !fir.ref}>>, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTscalar_and_array{r:f32,n:!fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}>}>) map_clauses(tofrom) capture(ByRef) members(%5, %10 : [1,0], [1,1] : !fir.ref, !fir.ref) -> !fir.ref}>> {name = "sa", partial_map = true} - omp.target map_entries(%11 -> %arg1 : !fir.ref}>>) { - omp.terminator - } - return + %0 = fir.declare %arg0 {uniq_name = "_QFmaptype_derived_nested_explicit_multiple_membersEsa"} : (!fir.ref}>>) -> !fir.ref}>> + %1 = fir.field_index n, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTscalar_and_array{r:f32,n:!fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}>}> + %2 = fir.coordinate_of %0, %1 : (!fir.ref}>>, !fir.field) -> !fir.ref> + %3 = fir.field_index i, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}> + %4 = fir.coordinate_of %2, %3 : (!fir.ref>, !fir.field) -> !fir.ref + %5 = omp.map.info var_ptr(%4 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "sa%n%i"} + %6 = fir.field_index n, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTscalar_and_array{r:f32,n:!fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}>}> + %7 = fir.coordinate_of %0, %6 : (!fir.ref}>>, !fir.field) -> !fir.ref> + %8 = fir.field_index r, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}> + %9 = fir.coordinate_of %7, %8 : (!fir.ref>, !fir.field) -> !fir.ref + %10 = omp.map.info var_ptr(%9 : !fir.ref, f32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "sa%n%r"} + %11 = omp.map.info var_ptr(%0 : !fir.ref}>>, !fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTscalar_and_array{r:f32,n:!fir.type<_QFmaptype_derived_nested_explicit_multiple_membersTnested{i:i32,r:f32}>}>) map_clauses(tofrom) capture(ByRef) members(%5, %10 : [1,0], [1,1] : !fir.ref, !fir.ref) -> !fir.ref}>> {name = "sa", partial_map = true} + omp.target map_entries(%11 -> %arg1 : !fir.ref}>>) { + omp.terminator } + return } // CHECK: func.func @test_nested_derived_type_map_operand_and_block_addition(%{{.*}}: !fir.ref}>>) { // CHECK: %[[MAP_MEMBER_1:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "sa%n%i"} // CHECK: %[[MAP_MEMBER_2:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref, f32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "sa%n%r"} -// CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_1]], %[[MAP_MEMBER_2]] : [1,0], [1,1] : !fir.ref, !fir.ref) -> {{.*}} {name = "sa", partial_map = true} -// CHECK: omp.target map_entries(%[[MAP_MEMBER_1]] -> %[[ARG1:.*]], %[[MAP_MEMBER_2]] -> %[[ARG2:.*]], %[[MAP_PARENT]] -> %[[ARG3:.*]] : !fir.ref, !fir.ref, {{.*}}) { +// CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER_1]], %[[MAP_MEMBER_2]] : [1, 0], [1, 1] : !fir.ref, !fir.ref) -> {{.*}} {name = "sa", partial_map = true} +// CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG1:.*]], %[[MAP_MEMBER_1]] -> %[[ARG2:.*]], %[[MAP_MEMBER_2]] -> %[[ARG3:.*]] : {{.*}}, !fir.ref, !fir.ref) { + +// ----- + +func.func @dtype_alloca_op_block_add(%arg0: !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) { + %0:2 = hlfir.declare %arg0 {uniq_name = "_QFtest_derived_type_allocatable_map_operand_and_block_additionEone_l"} : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) -> (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) + %1 = hlfir.designate %0#0{"array_j"} {fortran_attrs = #fir.var_attrs} : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) -> !fir.ref>>> + %2 = fir.load %1 : !fir.ref>>> + %c0_0 = arith.constant 0 : index + %3:3 = fir.box_dims %2, %c0_0 : (!fir.box>>, index) -> (index, index, index) + %c1_9 = arith.constant 1 : index + %c0_1 = arith.constant 0 : index + %4:3 = fir.box_dims %2, %c0_1 : (!fir.box>>, index) -> (index, index, index) + %c0_2 = arith.constant 0 : index + %5 = arith.subi %4#1, %c1_9 : index + %6 = omp.map.bounds lower_bound(%c0_2 : index) upper_bound(%5 : index) extent(%4#1 : index) stride(%4#2 : index) start_idx(%3#0 : index) {stride_in_bytes = true} + %c4 = arith.constant 4 : index + %7 = fir.coordinate_of %0#0, %c4 : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>, index) -> !fir.ref>>> + %8 = omp.map.info var_ptr(%7 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) bounds(%6) -> !fir.ref>>> {name = "one_l%array_j"} + %9 = omp.map.info var_ptr(%0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>, !fir.type<_QFtest_derived_type_allocatable_map_operand_and_block_additionTone_layer{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>) map_clauses(tofrom) capture(ByRef) members(%8 : [4] : !fir.ref>>>) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>> {name = "one_l", partial_map = true} + omp.target map_entries(%9 -> %arg1 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) { + omp.terminator + } + return +} + +// CHECK: func.func @dtype_alloca_op_block_add(%[[ARG0:.*]]: !fir.ref<[[REC_TY:!fir.type<_QFtest_derived_type_allocatable_map_operand_and_block_additionTone_layer{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}]]>>) { +// CHECK: %[[ALLOCA:.*]]:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref<[[REC_TY]]>>) -> (!fir.ref<[[REC_TY]]>>, !fir.ref<[[REC_TY]]>>) +// CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} +// CHECK: %[[MEMBER_COORD:.*]] = fir.coordinate_of %[[ALLOCA]]#0, %{{.*}} : (!fir.ref<[[REC_TY]]>>, index) -> !fir.ref>>> +// CHECK: %[[MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[MEMBER_COORD:.*]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[MAP_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[MAP_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[MEMBER_COORD]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {name = "one_l%array_j"} +// CHECK: %[[MAP_MEMBER_PARENT:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#0 : !fir.ref<[[REC_TY]]>>, [[REC_TY]]>) map_clauses(tofrom) capture(ByRef) members(%10, %9 : [4], [4, 0] : !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref<[[REC_TY]]>> {{.*}} +// CHECK: omp.target map_entries(%[[MAP_MEMBER_PARENT]] -> %[[ARG1:.*]], %[[MAP_MEMBER_DESCRIPTOR]] -> %[[ARG2:.*]], %[[MAP_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]] : !fir.ref<[[REC_TY]]>>, !fir.ref>>>, !fir.llvm_ptr>>) { + +// ----- + +func.func @alloca_dtype_map_op_block_add(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) { + %0:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_derived_type_map_operand_and_block_additionEone_l"} : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) -> (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) + %1 = fir.load %0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> + %2 = fir.box_addr %1 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>) -> !fir.heap>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>> + %3 = hlfir.designate %2{"array_j"} {fortran_attrs = #fir.var_attrs} : (!fir.heap>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>) -> !fir.ref>>> + %4 = fir.load %3 : !fir.ref>>> + %c0_0 = arith.constant 0 : index + %5:3 = fir.box_dims %4, %c0_0 : (!fir.box>>, index) -> (index, index, index) + %c1_0 = arith.constant 1 : index + %c0_1 = arith.constant 0 : index + %6:3 = fir.box_dims %4, %c0_1 : (!fir.box>>, index) -> (index, index, index) + %c0_2 = arith.constant 0 : index + %7 = arith.subi %6#1, %c1_0 : index + %8 = omp.map.bounds lower_bound(%c0_2 : index) upper_bound(%7 : index) extent(%6#1 : index) stride(%6#2 : index) start_idx(%5#0 : index) {stride_in_bytes = true} + %9 = fir.load %0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> + %c4 = arith.constant 4 : index + %10 = fir.coordinate_of %9, %c4 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>, index) -> !fir.ref>>> + %11 = omp.map.info var_ptr(%10 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) bounds(%8) -> !fir.ref>>> {name = "one_l%array_j"} + %12 = fir.load %0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> + %c5 = arith.constant 5 : index + %13 = fir.coordinate_of %12, %c5 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>, index) -> !fir.ref + %14 = omp.map.info var_ptr(%13 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "one_l%k"} + %15 = omp.map.info var_ptr(%0#1 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>, !fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>) map_clauses(tofrom) capture(ByRef) members(%11, %14 : [4], [5] : !fir.ref>>>, !fir.ref) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>> {name = "one_l", partial_map = true} + omp.target map_entries(%15 -> %arg1 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}>>>>) { + omp.terminator + } + return + } + +// CHECK: func.func @alloca_dtype_map_op_block_add(%[[ARG0:.*]]: !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32}]]>>>>) { +// CHECK: %[[ALLOCA:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_derived_type_map_operand_and_block_additionEone_l"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +// CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}}#1 : index) stride(%{{.*}}#2 : index) start_idx(%{{.*}}#0 : index) {stride_in_bytes = true} +// CHECK: %[[LOAD_ALLOCA:.*]] = fir.load %[[ALLOCA]]#0 : !fir.ref>>> +// CHECK: %[[ALLOCATABLE_MEMBER_COORD:.*]] = fir.coordinate_of %[[LOAD_ALLOCA]], %{{.*}} : (!fir.box>>, index) -> !fir.ref>>> +// CHECK: %[[ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCATABLE_MEMBER_COORD]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[MAP_ALLOCA_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER_COORD]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[ALLOCATABLE_MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[MAP_ALLOCA_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER_COORD]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +// CHECK: %[[LOAD_ALLOCA2:.*]] = fir.load %[[ALLOCA]]#0 : !fir.ref>>> +// CHECK: %[[REGULAR_MEMBER_COORD:.*]] = fir.coordinate_of %[[LOAD_ALLOCA2]], %{{.*}} : (!fir.box>>, index) -> !fir.ref +// CHECK: %[[MAP_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[REGULAR_MEMBER_COORD]] : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {{.*}} +// CHECK: %[[ALLOCATABLE_PARENT_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCA]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[MAP_ALLOCA_PARENT_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref>>>, !fir.type<[[REC_TY]]>) var_ptr_ptr(%[[ALLOCATABLE_PARENT_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[MAP_PARENT_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) members(%18, %13, %12, %16 : [0], [0, 4], [0, 4, 0], [0, 5] : !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) -> !fir.ref>>> {{.*}} +// CHECK: omp.target map_entries(%[[MAP_PARENT_DESCRIPTOR]] -> %[[ARG1:.*]], %[[MAP_ALLOCA_PARENT_BASE_ADDR]] -> %[[ARG2:.*]], %[[MAP_ALLOCA_MEMBER_DESCRIPTOR]] -> %[[ARG3:.*]], %[[MAP_ALLOCA_MEMBER_BASE_ADDR]] -> %[[ARG4:.*]], %[[MAP_REGULAR_MEMBER]] -> %[[ARG5:.*]] : !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) { + +// ----- + + func.func @alloca_nest_dtype_map_op_block_add(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) { + %0:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_alloca_nested_derived_type_map_operand_and_block_additionEone_l"} : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) -> (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) + %1 = fir.load %0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> + %2 = fir.box_addr %1 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>) -> !fir.heap>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>> + %3 = hlfir.designate %2{"nest"} : (!fir.heap>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + %4 = hlfir.designate %3{"array_k"} {fortran_attrs = #fir.var_attrs} : (!fir.ref,array_k:!fir.box>>,k:i32}>>) -> !fir.ref>>> + %5 = fir.load %4 : !fir.ref>>> + %c0_0 = arith.constant 0 : index + %6:3 = fir.box_dims %5, %c0_0 : (!fir.box>>, index) -> (index, index, index) + %c1_0 = arith.constant 1 : index + %c0_1 = arith.constant 0 : index + %7:3 = fir.box_dims %5, %c0_1 : (!fir.box>>, index) -> (index, index, index) + %8 = arith.subi %7#1, %c1_0 : index + %9 = omp.map.bounds lower_bound(%c0_1 : index) upper_bound(%8 : index) extent(%7#1 : index) stride(%7#2 : index) start_idx(%6#0 : index) {stride_in_bytes = true} + %10 = fir.load %0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> + %c6 = arith.constant 6 : index + %11 = fir.coordinate_of %10, %c6 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + %c2_0 = arith.constant 2 : index + %12 = fir.coordinate_of %11, %c2_0 : (!fir.ref,array_k:!fir.box>>,k:i32}>>, index) -> !fir.ref>>> + %13 = omp.map.info var_ptr(%12 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) bounds(%9) -> !fir.ref>>> {name = "one_l%nest%array_k"} + %14 = fir.load %0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> + %15 = fir.coordinate_of %14, %c6 : (!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + %c3 = arith.constant 3 : index + %16 = fir.coordinate_of %15, %c3 : (!fir.ref,array_k:!fir.box>>,k:i32}>>, index) -> !fir.ref + %17 = omp.map.info var_ptr(%16 : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {name = "one_l%nest%k"} + %18 = omp.map.info var_ptr(%0#1 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>, !fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>) map_clauses(tofrom) capture(ByRef) members(%13, %17 : [6,2], [6,3] : !fir.ref>>>, !fir.ref) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>> {name = "one_l", partial_map = true} + omp.target map_entries(%18 -> %arg1 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>>>) { + omp.terminator + } + return + } + +// CHECK: func.func @alloca_nest_dtype_map_op_block_add(%[[ARG0:.*]]: !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_alloca_nested_derived_type_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}]]>>>>) { +// CHECK: %[[ALLOCA:.*]]:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) +// CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} +// CHECK: %[[ALLOCA_LOAD:.*]] = fir.load %[[ALLOCA]]#0 : !fir.ref>>> +// CHECK: %[[INTERMEDIATE_DTYPE_NESTED_MEMBER:.*]] = fir.coordinate_of %[[ALLOCA_LOAD]], %{{.*}} : (!fir.box>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}]]>> +// CHECK: %[[NESTED_ALLOCA_MEMBER:.*]] = fir.coordinate_of %[[INTERMEDIATE_DTYPE_NESTED_MEMBER]], %{{.*}} : (!fir.ref>, index) -> !fir.ref>>> +// CHECK: %[[NESTED_ALLOCA_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[NESTED_ALLOCA_MEMBER]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[MAP_NESTED_ALLOCA_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCA_MEMBER]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[NESTED_ALLOCA_MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[MAP_NESTED_ALLOCA_MEMBER:.*]] = omp.map.info var_ptr(%[[NESTED_ALLOCA_MEMBER]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +// CHECK: %[[ALLOCA_LOAD2:.*]] = fir.load %[[ALLOCA]]#0 : !fir.ref>>> +// CHECK: %[[INTERMEDIATE_DTYPE_NESTED_MEMBER2:.*]] = fir.coordinate_of %[[ALLOCA_LOAD2]], %{{.*}} : (!fir.box>>, index) -> !fir.ref> +// CHECK: %[[NESTED_REGULAR_MEMBER:.*]] = fir.coordinate_of %[[INTERMEDIATE_DTYPE_NESTED_MEMBER2]], %{{.*}} : (!fir.ref>, index) -> !fir.ref +// CHECK: %[[MAP_NESTED_REGULAR_MEMBER:.*]] = omp.map.info var_ptr(%[[NESTED_REGULAR_MEMBER:.*]] : !fir.ref, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref {{.*}} +// CHECK: %[[ALLOCATABLE_PARENT_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCA]]#1 base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[MAP_ALLOCATABLE_PARENT_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref>>>, !fir.type<[[REC_TY]]>) var_ptr_ptr(%[[ALLOCATABLE_PARENT_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[MAP_ALLOCATABLE_PARENT_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#1 : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) members(%21, %15, %14, %19 : [0], [0, 6, 2], [0, 6, 2, 0], [0, 6, 3] : !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) -> !fir.ref>>> {{.*}} +// CHECK: omp.target map_entries(%[[MAP_ALLOCATABLE_PARENT_DESCRIPTOR]] -> %[[ARG1:.*]], %[[MAP_ALLOCATABLE_PARENT_BASE_ADDR]] -> %[[ARG2:.*]], %[[MAP_NESTED_ALLOCA_MEMBER]] -> %[[ARG3:.*]], %[[MAP_NESTED_ALLOCA_MEMBER_BASE_ADDR]] -> %[[ARG4:.*]], %[[MAP_NESTED_REGULAR_MEMBER]] -> %[[ARG5:.*]] : !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref>>>, !fir.llvm_ptr>>, !fir.ref) { + +// ----- + + func.func @nest_dtype_alloca_map_op_block_add(%arg0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) { + %0:2 = hlfir.declare %arg0 {uniq_name = "_QFtest_nested_derived_type_alloca_map_operand_and_block_additionEone_l"} : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) -> (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>, !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) + %1 = hlfir.designate %0#0{"nest"} : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + %2 = hlfir.designate %1{"array_k"} {fortran_attrs = #fir.var_attrs} : (!fir.ref,array_k:!fir.box>>,k:i32}>>) -> !fir.ref>>> + %3 = fir.load %2 : !fir.ref>>> + %c0_0 = arith.constant 0 : index + %4:3 = fir.box_dims %3, %c0_0 : (!fir.box>>, index) -> (index, index, index) + %c1_16 = arith.constant 1 : index + %c0_1 = arith.constant 0 : index + %5:3 = fir.box_dims %3, %c0_1 : (!fir.box>>, index) -> (index, index, index) + %c0_18 = arith.constant 0 : index + %6 = arith.subi %5#1, %c1_16 : index + %7 = omp.map.bounds lower_bound(%c0_18 : index) upper_bound(%6 : index) extent(%5#1 : index) stride(%5#2 : index) start_idx(%4#0 : index) {stride_in_bytes = true} + %c6_0 = arith.constant 6 : index + %8 = fir.coordinate_of %0#0, %c6_0 : (!fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}>> + %c2_0 = arith.constant 2 : index + %9 = fir.coordinate_of %8, %c2_0 : (!fir.ref,array_k:!fir.box>>,k:i32}>>, index) -> !fir.ref>>> + %10 = omp.map.info var_ptr(%9 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) bounds(%7) -> !fir.ref>>> {name = "one_l%nest%array_k"} + %11 = omp.map.info var_ptr(%0#0 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>, !fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTtop_layer{i:f32,scalar:!fir.box>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>) map_clauses(tofrom) capture(ByRef) members(%10 : [6,2] : !fir.ref>>>) -> !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>> {name = "one_l", partial_map = true} + omp.target map_entries(%11 -> %arg1 : !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}>>) { + omp.terminator + } + return + } + +// CHECK: func.func @nest_dtype_alloca_map_op_block_add(%[[ARG0:.*]]: !fir.ref>,array_i:!fir.array<10xi32>,j:f32,array_j:!fir.box>>,k:i32,nest:!fir.type<_QFtest_nested_derived_type_alloca_map_operand_and_block_additionTmiddle_layer{i:f32,array_i:!fir.array<10xi32>,array_k:!fir.box>>,k:i32}>}]]>>) { +// CHECK: %[[ALLOCA:.*]]:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +// CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} +// CHECK: %[[NESTED_DTYPE_COORD:.*]] = fir.coordinate_of %[[ALLOCA]]#0, %{{.*}} : (!fir.ref>, index) -> !fir.ref,array_k:!fir.box>>,k:i32}]]>> +// CHECK: %[[ALLOCATABLE_MEMBER:.*]] = fir.coordinate_of %[[NESTED_DTYPE_COORD]], %{{.*}} : (!fir.ref>, index) -> !fir.ref>>> +// CHECK: %[[ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = fir.box_offset %[[ALLOCATABLE_MEMBER]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[MAP_ALLOCATABLE_MEMBER_BASE_ADDR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[ALLOCATABLE_MEMBER_BASE_ADDR]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[MAP_ALLOCATABLE_MEMBER_DESCRIPTOR:.*]] = omp.map.info var_ptr(%[[ALLOCATABLE_MEMBER]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +// CHECK: %[[MAP_PARENT:.*]] = omp.map.info var_ptr(%[[ALLOCA]]#0 : !fir.ref>, !fir.type<[[REC_TY]]>) map_clauses(tofrom) capture(ByRef) members(%12, %11 : [6, 2], [6, 2, 0] : !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref> {{.*}} +// CHECK: omp.target map_entries(%[[MAP_PARENT]] -> %[[ARG1:.*]], %[[MAP_ALLOCATABLE_MEMBER_DESCRIPTOR]] -> %[[ARG2:.*]], %[[MAP_ALLOCATABLE_MEMBER_BASE_ADDR]] -> %[[ARG3:.*]] : !fir.ref>, !fir.ref>>>, !fir.llvm_ptr>>) { + +// ----- + + func.func @nest_dtype_mem_idx(%arg0 : !fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>) { + %0:2 = hlfir.declare %arg0 {uniq_name = "_QFmaptype_nested_derived_type_member_idxEalloca_dtype"} : (!fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>) -> (!fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>, !fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>) + %c1_15 = arith.constant 1 : index + %1 = omp.map.bounds lower_bound(%c1_15 : index) upper_bound(%c1_15 : index) extent(%c1_15 : index) stride(%c1_15 : index) start_idx(%c1_15 : index) {stride_in_bytes = true} + %2 = fir.coordinate_of %0#0, %c1_15 : (!fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>, index) -> !fir.ref>>,vertexy:!fir.box>>}>>>>> + %3 = omp.map.bounds lower_bound(%c1_15 : index) upper_bound(%c1_15 : index) extent(%c1_15 : index) stride(%c1_15 : index) start_idx(%c1_15 : index) {stride_in_bytes = true} + %4 = omp.map.info var_ptr(%2 : !fir.ref>>,vertexy:!fir.box>>}>>>>>, !fir.box>>,vertexy:!fir.box>>}>>>>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%3) -> !fir.ref>>,vertexy:!fir.box>>}>>>>> {name = "alloca_dtype%vertexes(2_8)%vertexy"} + %5 = fir.load %2 : !fir.ref>>,vertexy:!fir.box>>}>>>>> + %c2_i64 = arith.constant 2 : i64 + %c1_20 = arith.constant 1 : index + %6 = fir.convert %c2_i64 : (i64) -> index + %7 = arith.subi %6, %c1_20 : index + %8 = fir.coordinate_of %5, %7 : (!fir.box>>,vertexy:!fir.box>>}>>>>, index) -> !fir.ref>>,vertexy:!fir.box>>}>> + %c2_21 = arith.constant 2 : index + %9 = fir.coordinate_of %8, %c2_21 : (!fir.ref>>,vertexy:!fir.box>>}>>, index) -> !fir.ref>>> + %10 = omp.map.info var_ptr(%9 : !fir.ref>>>, !fir.box>>) map_clauses(tofrom) capture(ByRef) bounds(%1) -> !fir.ref>>> {name = "alloca_dtype%vertexes(2_8)%vertexy"} + %11 = omp.map.info var_ptr(%0#1 : !fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>, !fir.type<_QFmaptype_nested_derived_type_member_idxTdtype{i:f32,vertexes:!fir.box>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) members(%4, %10 : [1], [1,2] : !fir.ref>>,vertexy:!fir.box>>}>>>>>, !fir.ref>>>) -> !fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>> {name = "alloca_dtype", partial_map = true} + omp.target map_entries(%11 -> %arg1 : !fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}>>) { + omp.terminator + } + return + } + +// CHECK: func.func @nest_dtype_mem_idx(%[[ARG0:.*]]: !fir.ref>>,vertexy:!fir.box>>}>>>>,array_i:!fir.array<10xi32>}]]>>) { +// CHECK: %[[DECLARE:.*]]:2 = hlfir.declare %[[ARG0]] {{.*}} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +// CHECK: %[[DESC_1:.*]] = fir.coordinate_of %[[DECLARE]]#0, %{{.*}} : (!fir.ref>, index) -> !fir.ref>>,vertexy:!fir.box>>}]]>>>>> +// CHECK: %[[BASE_ADDR_1:.*]] = fir.box_offset %[[DESC_1]] base_addr : (!fir.ref>>>>) -> !fir.llvm_ptr>>> +// CHECK: %[[BASE_ADDR_MAP_1:.*]] = omp.map.info var_ptr(%[[DESC_1]] : !fir.ref>>>>, !fir.array>) var_ptr_ptr(%[[BASE_ADDR_1]] : !fir.llvm_ptr>>>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%{{.*}}) -> !fir.llvm_ptr>>> {{.*}} +// CHECK: %[[DESC_MAP_1:.*]] = omp.map.info var_ptr(%[[DESC_1]] : !fir.ref>>>>, !fir.box>>>) map_clauses(to) capture(ByRef) -> !fir.ref>>>> {{.*}} +// CHECK: %[[DESC_LD_1:.*]] = fir.load %[[DESC_1]] : !fir.ref>>>> +// CHECK: %[[MEMBER_ACCESS_1:.*]] = fir.coordinate_of %[[DESC_LD_1]], %{{.*}} : (!fir.box>>>, index) -> !fir.ref> +// CHECK: %[[DESC_2:.*]] = fir.coordinate_of %[[MEMBER_ACCESS_1]], %{{.*}} : (!fir.ref>, index) -> !fir.ref>>> +// CHECK: %[[BASE_ADDR_2:.*]] = fir.box_offset %[[DESC_2]] base_addr : (!fir.ref>>>) -> !fir.llvm_ptr>> +// CHECK: %[[BASE_ADDR_MAP_2:.*]] = omp.map.info var_ptr(%[[DESC_2]] : !fir.ref>>>, !fir.array) var_ptr_ptr(%[[BASE_ADDR_2]] : !fir.llvm_ptr>>) map_clauses(tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.llvm_ptr>> {{.*}} +// CHECK: %[[DESC_MAP_2:.*]] = omp.map.info var_ptr(%[[DESC_2]] : !fir.ref>>>, !fir.box>>) map_clauses(to) capture(ByRef) -> !fir.ref>>> {{.*}} +// CHECK: %[[TOP_PARENT_MAP:.*]] = omp.map.info var_ptr(%0#1 : !fir.ref>, !fir.type<[[REC_TY]]>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) members(%6, %5, %14, %13 : [1], [1, 0], [1, 0, 2], [1, 0, 2, 0] : !fir.ref>>>>, !fir.llvm_ptr>>>, !fir.ref>>>, !fir.llvm_ptr>>) -> !fir.ref> {{{.*}} partial_map = true} +// CHECK: omp.target map_entries(%[[TOP_PARENT_MAP]] -> %{{.*}}, %[[DESC_MAP_1]] -> %{{.*}}, %[[BASE_ADDR_MAP_1]] -> %{{.*}}, %[[DESC_MAP_2]] -> %{{.*}}, %[[BASE_ADDR_MAP_2]] -> %{{.*}} : !fir.ref>, !fir.ref>>>>, !fir.llvm_ptr>>>, !fir.ref>>>, !fir.llvm_ptr>>) { diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp index fe5e36f704c76cf9ce3dea335308399001d868e3..1c24979bbcdafb5f6668e88815a939415a15f40c 100644 --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -452,7 +452,8 @@ static llvm::LogicalResult convertFortranSourceToMLIR( if (emitFIR && useHLFIR) { // lower HLFIR to FIR - fir::createHLFIRToFIRPassPipeline(pm, llvm::OptimizationLevel::O2); + fir::createHLFIRToFIRPassPipeline(pm, enableOpenMP, + llvm::OptimizationLevel::O2); if (mlir::failed(pm.run(mlirModule))) { llvm::errs() << "FATAL: lowering from HLFIR to FIR failed"; return mlir::failure(); @@ -467,6 +468,8 @@ static llvm::LogicalResult convertFortranSourceToMLIR( // Add O2 optimizer pass pipeline. MLIRToLLVMPassPipelineConfig config(llvm::OptimizationLevel::O2); + if (enableOpenMP) + config.EnableOpenMP = true; config.NSWOnLoopVarInc = setNSW; fir::registerDefaultInlinerPass(config); fir::createDefaultFIROptimizerPassPipeline(pm, config); diff --git a/flang/tools/tco/tco.cpp b/flang/tools/tco/tco.cpp index 5c373c4e85258cace008081cc06eef1cf2f0c416..eaf4bae0884546adbf53aecdd5a93fb3c0852237 100644 --- a/flang/tools/tco/tco.cpp +++ b/flang/tools/tco/tco.cpp @@ -139,6 +139,7 @@ compileFIR(const mlir::PassPipelineCLParser &passPipeline) { return mlir::failure(); } else { MLIRToLLVMPassPipelineConfig config(llvm::OptimizationLevel::O2); + config.EnableOpenMP = true; // assume the input contains OpenMP config.AliasAnalysis = true; // enabled when optimizing for speed if (codeGenLLVM) { // Run only CodeGen passes. diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index c393d23a3b33d4cdd740aa27668bf13eaaf3dfcf..77b659b2ef232275f066a5ecbf2ae2e19551cd4d 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -248,10 +248,17 @@ foreach(config_path IN LISTS LIBC_CONFIG_JSON_FILE_LIST) load_libc_config(${config_path}/config.json ${cmd_line_conf}) endforeach() +if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) + set(LIBC_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE}) + if(LIBC_LIBDIR_SUBDIR) + string(APPEND LIBC_TARGET_SUBDIR /${LIBC_LIBDIR_SUBDIR}) + endif() +endif() + if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND (LIBC_ENABLE_USE_BY_CLANG OR LIBC_TARGET_OS_IS_GPU)) set(LIBC_INCLUDE_DIR ${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}) set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) - set(LIBC_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBC_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LIBC_TARGET_SUBDIR}) else() if(NOT LIBC_ENABLE_USE_BY_CLANG) set(LIBC_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) @@ -277,8 +284,7 @@ endif() if(LIBC_TARGET_TRIPLE) set(LIBC_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LIBC_TARGET_TRIPLE}) elseif(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) - set(LIBC_INSTALL_LIBRARY_DIR - lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}) + set(LIBC_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LIBC_TARGET_SUBDIR}) else() set(LIBC_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}) endif() diff --git a/libc/benchmarks/CMakeLists.txt b/libc/benchmarks/CMakeLists.txt index 0cff6eb12c2475aba9f9d099253a1ae17b95e605..52e3f942d16ea34b772e592736e3d9630384a8fb 100644 --- a/libc/benchmarks/CMakeLists.txt +++ b/libc/benchmarks/CMakeLists.txt @@ -126,6 +126,7 @@ add_library(libc-memory-benchmark target_include_directories(libc-memory-benchmark PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBC_SOURCE_DIR} ) target_link_libraries(libc-memory-benchmark PUBLIC diff --git a/libc/benchmarks/LibcBenchmark.h b/libc/benchmarks/LibcBenchmark.h index 0a0b40f924e68ec8bfe564d9735210c3e9ad1841..6b1556721e416f3ba9de270a9b9259b8c92a678c 100644 --- a/libc/benchmarks/LibcBenchmark.h +++ b/libc/benchmarks/LibcBenchmark.h @@ -211,7 +211,7 @@ BenchmarkResult benchmark(const BenchmarkOptions &Options, // Measuring this Batch. const auto StartTime = Clock.now(); for (const auto Parameter : Batch) { - const auto Production = foo(Parameter); + auto Production = foo(Parameter); benchmark::DoNotOptimize(Production); } const auto EndTime = Clock.now(); diff --git a/libc/benchmarks/MemorySizeDistributions.cpp b/libc/benchmarks/MemorySizeDistributions.cpp index c3590297445dd1aabe910fc4b8c312bd60dae472..e29b3710f736732ece3257db970ca760761b9c70 100644 --- a/libc/benchmarks/MemorySizeDistributions.cpp +++ b/libc/benchmarks/MemorySizeDistributions.cpp @@ -185,12 +185,10 @@ ArrayRef getMemcmpSizeDistributions() { MemorySizeDistribution getDistributionOrDie(ArrayRef Distributions, StringRef Name) { - size_t Index = 0; - for (const auto &MSD : Distributions) { + for (const auto &MSD : Distributions) if (MSD.Name == Name) return MSD; - ++Index; - } + std::string Message; raw_string_ostream Stream(Message); Stream << "Unknown MemorySizeDistribution '" << Name diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt index 28fd1ce9128d25ae4c814dc68474c9a9faa3c54c..6cc8a80455d3ac8ec3fcafdf8ec615fddba51541 100644 --- a/libc/config/baremetal/arm/headers.txt +++ b/libc/config/baremetal/arm/headers.txt @@ -2,6 +2,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.assert libc.include.ctype libc.include.errno + libc.include.features libc.include.fenv libc.include.float libc.include.inttypes diff --git a/libc/config/baremetal/riscv/headers.txt b/libc/config/baremetal/riscv/headers.txt index 3608364e45bdeb31f2caeae493755d357238efc0..c4fa24f025a71fb46f6fc81382a7ef0e5f2e0a14 100644 --- a/libc/config/baremetal/riscv/headers.txt +++ b/libc/config/baremetal/riscv/headers.txt @@ -1,13 +1,14 @@ set(TARGET_PUBLIC_HEADERS libc.include.assert libc.include.ctype - libc.include.fenv libc.include.errno + libc.include.features + libc.include.fenv libc.include.float - libc.include.stdint libc.include.inttypes libc.include.math libc.include.stdfix + libc.include.stdint libc.include.stdio libc.include.stdlib libc.include.string diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 3758f0809960e52945d9c35752e8f6c431836754..5419462d4f5b3bae8cccf08ae5d86cd31874a58c 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -728,8 +728,8 @@ if(LIBC_COMPILER_HAS_FIXED_POINT) libc.src.stdfix.kbits libc.src.stdfix.ukbits # TODO: https://github.com/llvm/llvm-project/issues/115778 - # libc.src.stdfix.lkbits - # libc.src.stdfix.ulkbits + libc.src.stdfix.lkbits + libc.src.stdfix.ulkbits ) endif() diff --git a/libc/docs/gpu/rpc.rst b/libc/docs/gpu/rpc.rst index ee5865d7f64079037e830d947b67906b80ba43ea..e1244154341e9f9300ef81eabd4b27fb69b60ec0 100644 --- a/libc/docs/gpu/rpc.rst +++ b/libc/docs/gpu/rpc.rst @@ -302,6 +302,6 @@ associated with relocatable device code linking. Extensions ---------- -We describe which operation the RPC server should take with a 16-bit opcode. We -consider the first 32768 numbers to be reserved while the others are free to -use. +The opcode is a 32-bit integer that must be unique to the requested operation. +All opcodes used by ``libc`` internally have the character ``c`` in the most +significant byte. diff --git a/libc/docs/talks.rst b/libc/docs/talks.rst index 174de0f56e7dd44cdde7ebaa192603556e0fe734..7e560964d6aa5f11a4846e57457b538a70f12218 100644 --- a/libc/docs/talks.rst +++ b/libc/docs/talks.rst @@ -12,6 +12,10 @@ Talks * `slides `__ * `video `__ +* The Challenges of Implementing the C Standard Library in C++ - Sivachandra Reddy + + * `slides `__ + * `video `__ ---- 2022 diff --git a/libc/fuzzing/__support/hashtable_fuzz.cpp b/libc/fuzzing/__support/hashtable_fuzz.cpp index 7d61e106c9c4a3edb1c7d860c6de9d1542933fe1..8ab5e3b55cfd4bec13f733d1055f4d8bb9a9797d 100644 --- a/libc/fuzzing/__support/hashtable_fuzz.cpp +++ b/libc/fuzzing/__support/hashtable_fuzz.cpp @@ -10,6 +10,7 @@ /// //===----------------------------------------------------------------------===// #include "include/llvm-libc-types/ENTRY.h" +#include "src/__support/CPP/bit.h" #include "src/__support/CPP/string_view.h" #include "src/__support/HashTable/table.h" #include "src/__support/macros/config.h" @@ -81,15 +82,14 @@ static struct { template T next() { static_assert(cpp::is_integral::value, "T must be an integral type"); - union { - T result; - char data[sizeof(T)]; - }; - for (size_t i = 0; i < sizeof(result); i++) + + char data[sizeof(T)]; + + for (size_t i = 0; i < sizeof(T); i++) data[i] = buffer[i]; - buffer += sizeof(result); - remaining -= sizeof(result); - return result; + buffer += sizeof(T); + remaining -= sizeof(T); + return cpp::bit_cast(data); } cpp::string_view next_string() { diff --git a/libc/include/llvm-libc-types/rpc_opcodes_t.h b/libc/include/llvm-libc-types/rpc_opcodes_t.h index 1a6c0cd9bc4a14d01ec43cce1ba594bc8bc69d49..f3b35518935a54925ac998e891c850ab3a172d6e 100644 --- a/libc/include/llvm-libc-types/rpc_opcodes_t.h +++ b/libc/include/llvm-libc-types/rpc_opcodes_t.h @@ -9,38 +9,41 @@ #ifndef LLVM_LIBC_TYPES_RPC_OPCODES_T_H #define LLVM_LIBC_TYPES_RPC_OPCODES_T_H +#define LLVM_LIBC_RPC_BASE 'c' +#define LLVM_LIBC_OPCODE(n) (LLVM_LIBC_RPC_BASE << 24 | n) + typedef enum { - RPC_NOOP = 0, - RPC_EXIT, - RPC_WRITE_TO_STDOUT, - RPC_WRITE_TO_STDERR, - RPC_WRITE_TO_STREAM, - RPC_WRITE_TO_STDOUT_NEWLINE, - RPC_READ_FROM_STREAM, - RPC_READ_FGETS, - RPC_OPEN_FILE, - RPC_CLOSE_FILE, - RPC_MALLOC, - RPC_FREE, - RPC_HOST_CALL, - RPC_ABORT, - RPC_FEOF, - RPC_FERROR, - RPC_CLEARERR, - RPC_FSEEK, - RPC_FTELL, - RPC_FFLUSH, - RPC_UNGETC, - RPC_PRINTF_TO_STDOUT, - RPC_PRINTF_TO_STDERR, - RPC_PRINTF_TO_STREAM, - RPC_PRINTF_TO_STDOUT_PACKED, - RPC_PRINTF_TO_STDERR_PACKED, - RPC_PRINTF_TO_STREAM_PACKED, - RPC_REMOVE, - RPC_RENAME, - RPC_SYSTEM, - RPC_LAST = 0xFFFF, + RPC_NOOP = LLVM_LIBC_OPCODE(0), + RPC_EXIT = LLVM_LIBC_OPCODE(1), + RPC_WRITE_TO_STDOUT = LLVM_LIBC_OPCODE(2), + RPC_WRITE_TO_STDERR = LLVM_LIBC_OPCODE(3), + RPC_WRITE_TO_STREAM = LLVM_LIBC_OPCODE(4), + RPC_WRITE_TO_STDOUT_NEWLINE = LLVM_LIBC_OPCODE(5), + RPC_READ_FROM_STREAM = LLVM_LIBC_OPCODE(6), + RPC_READ_FGETS = LLVM_LIBC_OPCODE(7), + RPC_OPEN_FILE = LLVM_LIBC_OPCODE(8), + RPC_CLOSE_FILE = LLVM_LIBC_OPCODE(9), + RPC_MALLOC = LLVM_LIBC_OPCODE(10), + RPC_FREE = LLVM_LIBC_OPCODE(11), + RPC_HOST_CALL = LLVM_LIBC_OPCODE(12), + RPC_ABORT = LLVM_LIBC_OPCODE(13), + RPC_FEOF = LLVM_LIBC_OPCODE(14), + RPC_FERROR = LLVM_LIBC_OPCODE(15), + RPC_CLEARERR = LLVM_LIBC_OPCODE(16), + RPC_FSEEK = LLVM_LIBC_OPCODE(17), + RPC_FTELL = LLVM_LIBC_OPCODE(18), + RPC_FFLUSH = LLVM_LIBC_OPCODE(19), + RPC_UNGETC = LLVM_LIBC_OPCODE(20), + RPC_PRINTF_TO_STDOUT = LLVM_LIBC_OPCODE(21), + RPC_PRINTF_TO_STDERR = LLVM_LIBC_OPCODE(22), + RPC_PRINTF_TO_STREAM = LLVM_LIBC_OPCODE(23), + RPC_PRINTF_TO_STDOUT_PACKED = LLVM_LIBC_OPCODE(24), + RPC_PRINTF_TO_STDERR_PACKED = LLVM_LIBC_OPCODE(25), + RPC_PRINTF_TO_STREAM_PACKED = LLVM_LIBC_OPCODE(26), + RPC_REMOVE = LLVM_LIBC_OPCODE(27), + RPC_RENAME = LLVM_LIBC_OPCODE(28), + RPC_SYSTEM = LLVM_LIBC_OPCODE(29), + RPC_LAST = 0xFFFFFFFF, } rpc_opcode_t; #endif // LLVM_LIBC_TYPES_RPC_OPCODES_T_H diff --git a/libc/include/llvm-libc-types/stdfix-types.h b/libc/include/llvm-libc-types/stdfix-types.h index 759e59251a5e8700132921adce162a665837dbff..542d45ea97e96fc976e4f6d07074f931130e00f6 100644 --- a/libc/include/llvm-libc-types/stdfix-types.h +++ b/libc/include/llvm-libc-types/stdfix-types.h @@ -14,12 +14,12 @@ typedef signed short int int_r_t; typedef signed int int_lr_t; typedef signed short int_hk_t; typedef signed int int_k_t; -typedef signed long int_lk_t; +typedef signed long long int_lk_t; typedef unsigned char uint_uhr_t; typedef unsigned short int uint_ur_t; typedef unsigned int uint_ulr_t; typedef unsigned short int uint_uhk_t; typedef unsigned int uint_uk_t; -typedef unsigned long uint_ulk_t; +typedef unsigned long long uint_ulk_t; #endif // LLVM_LIBC_TYPES_STDFIX_TYPES_H diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index c44e333645e22e31827dbb6455087fd5b262d17f..6637ff9d56f4bcf568cda4656fead3c192617c6b 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -55,7 +55,7 @@ add_header_library( common HDRS common.h - endian.h + endian_internal.h macros/properties/architectures.h macros/attributes.h macros/properties/cpu_features.h diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 6da89091a8ced9ab4f33e81c1e20f3b76031faf9..90b6e406e0f31fd8ef4f5c3bc56fb5be7b4e9a29 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -127,7 +127,11 @@ template <> struct FPLayout { }; template <> struct FPLayout { +#if __SIZEOF_LONG_DOUBLE__ == 12 + using StorageType = UInt<__SIZEOF_LONG_DOUBLE__ * CHAR_BIT>; +#else using StorageType = UInt128; +#endif LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1; LIBC_INLINE_VAR static constexpr int EXP_LEN = 15; LIBC_INLINE_VAR static constexpr int SIG_LEN = 64; diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h index 053348d4c975dadfd46e17e1cf7902db06df8ebc..9492d52da04558f3298b6d4578fe6a202b5ac61c 100644 --- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h +++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h @@ -21,7 +21,8 @@ namespace LIBC_NAMESPACE_DECL { namespace fputil { namespace x86 { -LIBC_INLINE void normalize(int &exponent, UInt128 &mantissa) { +LIBC_INLINE void normalize(int &exponent, + FPBits::StorageType &mantissa) { const unsigned int shift = static_cast( cpp::countl_zero(static_cast(mantissa)) - (8 * sizeof(uint64_t) - 1 - FPBits::FRACTION_LEN)); diff --git a/libc/src/__support/HashTable/generic/bitmask_impl.inc b/libc/src/__support/HashTable/generic/bitmask_impl.inc index 6266ac3c84a9005ac49742f55839ff44fef51860..d526dc1ece293dee9964cc95c99ad8e880e199db 100644 --- a/libc/src/__support/HashTable/generic/bitmask_impl.inc +++ b/libc/src/__support/HashTable/generic/bitmask_impl.inc @@ -6,8 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/CPP/bit.h" #include "src/__support/common.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { @@ -44,13 +45,11 @@ struct Group { // Load a group of control words from an arbitary address. LIBC_INLINE static Group load(const void *addr) { - union { - bitmask_t value; - char bytes[sizeof(bitmask_t)]; - } data; + char bytes[sizeof(bitmask_t)]; + for (size_t i = 0; i < sizeof(bitmask_t); ++i) - data.bytes[i] = static_cast(addr)[i]; - return {data.value}; + bytes[i] = static_cast(addr)[i]; + return Group{cpp::bit_cast(bytes)}; } // Load a group of control words from an aligned address. diff --git a/libc/src/__support/OSUtil/gpu/exit.cpp b/libc/src/__support/OSUtil/gpu/exit.cpp index 8aaa41b4e3eefc55b117b294105c512aa1ba0398..0cb266a42d180a2506da46af8641b6d8d2de8460 100644 --- a/libc/src/__support/OSUtil/gpu/exit.cpp +++ b/libc/src/__support/OSUtil/gpu/exit.cpp @@ -8,6 +8,7 @@ #include "src/__support/OSUtil/exit.h" +#include "src/__support/GPU/utils.h" #include "src/__support/RPC/rpc_client.h" #include "src/__support/macros/config.h" #include "src/__support/macros/properties/architectures.h" diff --git a/libc/src/__support/RPC/rpc.h b/libc/src/__support/RPC/rpc.h index c421dd82b2945031d696b0f6dcfa5b9d15d01686..30dd2c1a8125d74e5cc805fa67cebf9b9c062e48 100644 --- a/libc/src/__support/RPC/rpc.h +++ b/libc/src/__support/RPC/rpc.h @@ -19,10 +19,7 @@ #define LLVM_LIBC_SRC___SUPPORT_RPC_RPC_H #include "rpc_util.h" -#include "src/__support/CPP/algorithm.h" // max -#include "src/__support/CPP/atomic.h" -#include "src/__support/CPP/optional.h" -#include "src/__support/GPU/utils.h" +#include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" #include @@ -30,6 +27,20 @@ namespace LIBC_NAMESPACE_DECL { namespace rpc { +/// Use scoped atomic variants if they are available for the target. +#if !__has_builtin(__scoped_atomic_load_n) +#define __scoped_atomic_load_n(src, ord, scp) __atomic_load_n(src, ord) +#define __scoped_atomic_store_n(dst, src, ord, scp) \ + __atomic_store_n(dst, src, ord) +#define __scoped_atomic_fetch_or(src, val, ord, scp) \ + __atomic_fetch_or(src, val, ord) +#define __scoped_atomic_fetch_and(src, val, ord, scp) \ + __atomic_fetch_and(src, val, ord) +#endif +#if !__has_builtin(__scoped_atomic_thread_fence) +#define __scoped_atomic_thread_fence(ord, scp) __atomic_thread_fence(ord) +#endif + /// A fixed size channel used to communicate between the RPC client and server. struct Buffer { uint64_t data[8]; @@ -40,11 +51,11 @@ static_assert(sizeof(Buffer) == 64, "Buffer size mismatch"); /// perform and which threads are active in the slots. struct Header { uint64_t mask; - uint16_t opcode; + uint32_t opcode; }; /// The maximum number of parallel ports that the RPC interface can support. -constexpr uint64_t MAX_PORT_COUNT = 4096; +constexpr static uint64_t MAX_PORT_COUNT = 4096; /// A common process used to synchronize communication between a client and a /// server. The process contains a read-only inbox and a write-only outbox used @@ -67,18 +78,18 @@ template struct Process { LIBC_INLINE ~Process() = default; uint32_t port_count = 0; - cpp::Atomic *inbox = nullptr; - cpp::Atomic *outbox = nullptr; + uint32_t *inbox = nullptr; + uint32_t *outbox = nullptr; Header *header = nullptr; Buffer *packet = nullptr; static constexpr uint64_t NUM_BITS_IN_WORD = sizeof(uint32_t) * 8; - cpp::Atomic lock[MAX_PORT_COUNT / NUM_BITS_IN_WORD] = {0}; + uint32_t lock[MAX_PORT_COUNT / NUM_BITS_IN_WORD] = {0}; LIBC_INLINE Process(uint32_t port_count, void *buffer) - : port_count(port_count), inbox(reinterpret_cast *>( + : port_count(port_count), inbox(reinterpret_cast( advance(buffer, inbox_offset(port_count)))), - outbox(reinterpret_cast *>( + outbox(reinterpret_cast( advance(buffer, outbox_offset(port_count)))), header(reinterpret_cast
( advance(buffer, header_offset(port_count)))), @@ -101,16 +112,16 @@ template struct Process { /// Retrieve the inbox state from memory shared between processes. LIBC_INLINE uint32_t load_inbox(uint64_t lane_mask, uint32_t index) const { - return gpu::broadcast_value( - lane_mask, - inbox[index].load(cpp::MemoryOrder::RELAXED, cpp::MemoryScope::SYSTEM)); + return rpc::broadcast_value( + lane_mask, __scoped_atomic_load_n(&inbox[index], __ATOMIC_RELAXED, + __MEMORY_SCOPE_SYSTEM)); } /// Retrieve the outbox state from memory shared between processes. LIBC_INLINE uint32_t load_outbox(uint64_t lane_mask, uint32_t index) const { - return gpu::broadcast_value(lane_mask, - outbox[index].load(cpp::MemoryOrder::RELAXED, - cpp::MemoryScope::SYSTEM)); + return rpc::broadcast_value( + lane_mask, __scoped_atomic_load_n(&outbox[index], __ATOMIC_RELAXED, + __MEMORY_SCOPE_SYSTEM)); } /// Signal to the other process that this one is finished with the buffer. @@ -119,9 +130,9 @@ template struct Process { /// cheaper than calling load_outbox to get the value to store. LIBC_INLINE uint32_t invert_outbox(uint32_t index, uint32_t current_outbox) { uint32_t inverted_outbox = !current_outbox; - atomic_thread_fence(cpp::MemoryOrder::RELEASE); - outbox[index].store(inverted_outbox, cpp::MemoryOrder::RELAXED, - cpp::MemoryScope::SYSTEM); + __scoped_atomic_thread_fence(__ATOMIC_RELEASE, __MEMORY_SCOPE_SYSTEM); + __scoped_atomic_store_n(&outbox[index], inverted_outbox, __ATOMIC_RELAXED, + __MEMORY_SCOPE_SYSTEM); return inverted_outbox; } @@ -133,7 +144,7 @@ template struct Process { sleep_briefly(); in = load_inbox(lane_mask, index); } - atomic_thread_fence(cpp::MemoryOrder::ACQUIRE); + __scoped_atomic_thread_fence(__ATOMIC_ACQUIRE, __MEMORY_SCOPE_SYSTEM); } /// The packet is a linearly allocated array of buffers used to communicate @@ -153,10 +164,9 @@ template struct Process { /// Attempt to claim the lock at index. Return true on lock taken. /// lane_mask is a bitmap of the threads in the warp that would hold the - /// single lock on success, e.g. the result of gpu::get_lane_mask() + /// single lock on success, e.g. the result of rpc::get_lane_mask() /// The lock is held when the n-th bit of the lock bitfield is set. - [[clang::convergent]] LIBC_INLINE bool try_lock(uint64_t lane_mask, - uint32_t index) { + LIBC_INLINE bool try_lock(uint64_t lane_mask, uint32_t index) { // On amdgpu, test and set to the nth lock bit and a sync_lane would suffice // On volta, need to handle differences between the threads running and // the threads that were detected in the previous call to get_lane_mask() @@ -165,12 +175,12 @@ template struct Process { // There may be threads active which are not in lane mask which must not // succeed in taking the lock, as otherwise it will leak. This is handled // by making threads which are not in lane_mask or with 0, a no-op. - uint32_t id = gpu::get_lane_id(); + uint32_t id = rpc::get_lane_id(); bool id_in_lane_mask = lane_mask & (1ul << id); // All threads in the warp call fetch_or. Possibly at the same time. bool before = set_nth(lock, index, id_in_lane_mask); - uint64_t packed = gpu::ballot(lane_mask, before); + uint64_t packed = rpc::ballot(lane_mask, before); // If every bit set in lane_mask is also set in packed, every single thread // in the warp failed to get the lock. Ballot returns unset for threads not @@ -190,28 +200,27 @@ template struct Process { // inlining the current function. bool holding_lock = lane_mask != packed; if (holding_lock) - atomic_thread_fence(cpp::MemoryOrder::ACQUIRE); + __scoped_atomic_thread_fence(__ATOMIC_ACQUIRE, __MEMORY_SCOPE_DEVICE); return holding_lock; } /// Unlock the lock at index. We need a lane sync to keep this function /// convergent, otherwise the compiler will sink the store and deadlock. - [[clang::convergent]] LIBC_INLINE void unlock(uint64_t lane_mask, - uint32_t index) { + LIBC_INLINE void unlock(uint64_t lane_mask, uint32_t index) { // Do not move any writes past the unlock. - atomic_thread_fence(cpp::MemoryOrder::RELEASE); + __scoped_atomic_thread_fence(__ATOMIC_RELEASE, __MEMORY_SCOPE_DEVICE); // Use exactly one thread to clear the nth bit in the lock array Must // restrict to a single thread to avoid one thread dropping the lock, then // an unrelated warp claiming the lock, then a second thread in this warp // dropping the lock again. - clear_nth(lock, index, gpu::is_first_lane(lane_mask)); - gpu::sync_lane(lane_mask); + clear_nth(lock, index, rpc::is_first_lane(lane_mask)); + rpc::sync_lane(lane_mask); } /// Number of bytes to allocate for an inbox or outbox. LIBC_INLINE static constexpr uint64_t mailbox_bytes(uint32_t port_count) { - return port_count * sizeof(cpp::Atomic); + return port_count * sizeof(uint32_t); } /// Number of bytes to allocate for the buffer containing the packets. @@ -242,24 +251,24 @@ template struct Process { } /// Conditionally set the n-th bit in the atomic bitfield. - LIBC_INLINE static constexpr uint32_t set_nth(cpp::Atomic *bits, - uint32_t index, bool cond) { + LIBC_INLINE static constexpr uint32_t set_nth(uint32_t *bits, uint32_t index, + bool cond) { uint32_t slot = index / NUM_BITS_IN_WORD; uint32_t bit = index % NUM_BITS_IN_WORD; - return bits[slot].fetch_or(static_cast(cond) << bit, - cpp::MemoryOrder::RELAXED, - cpp::MemoryScope::DEVICE) & + return __scoped_atomic_fetch_or(&bits[slot], + static_cast(cond) << bit, + __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE) & (1u << bit); } /// Conditionally clear the n-th bit in the atomic bitfield. - LIBC_INLINE static constexpr uint32_t clear_nth(cpp::Atomic *bits, + LIBC_INLINE static constexpr uint32_t clear_nth(uint32_t *bits, uint32_t index, bool cond) { uint32_t slot = index / NUM_BITS_IN_WORD; uint32_t bit = index % NUM_BITS_IN_WORD; - return bits[slot].fetch_and(~0u ^ (static_cast(cond) << bit), - cpp::MemoryOrder::RELAXED, - cpp::MemoryScope::DEVICE) & + return __scoped_atomic_fetch_and(&bits[slot], + ~0u ^ (static_cast(cond) << bit), + __ATOMIC_RELAXED, __MEMORY_SCOPE_DEVICE) & (1u << bit); } }; @@ -269,9 +278,9 @@ template LIBC_INLINE static void invoke_rpc(F &&fn, uint32_t lane_size, uint64_t lane_mask, Buffer *slot) { if constexpr (is_process_gpu()) { - fn(&slot[gpu::get_lane_id()], gpu::get_lane_id()); + fn(&slot[rpc::get_lane_id()], rpc::get_lane_id()); } else { - for (uint32_t i = 0; i < lane_size; i += gpu::get_lane_size()) + for (uint32_t i = 0; i < lane_size; i += rpc::get_num_lanes()) if (lane_mask & (1ul << i)) fn(&slot[i], i); } @@ -295,7 +304,7 @@ private: friend struct Client; friend struct Server; - friend class cpp::optional>; + friend class rpc::optional>; public: template LIBC_INLINE void recv(U use); @@ -308,15 +317,15 @@ public: template LIBC_INLINE void recv_n(void **dst, uint64_t *size, A &&alloc); - LIBC_INLINE uint16_t get_opcode() const { + LIBC_INLINE uint32_t get_opcode() const { return process.header[index].opcode; } - LIBC_INLINE uint16_t get_index() const { return index; } + LIBC_INLINE uint32_t get_index() const { return index; } LIBC_INLINE void close() { // Wait for all lanes to finish using the port. - gpu::sync_lane(lane_mask); + rpc::sync_lane(lane_mask); // The server is passive, if it own the buffer when it closes we need to // give ownership back to the client. @@ -346,14 +355,11 @@ struct Client { : process(port_count, buffer) {} using Port = rpc::Port; - template LIBC_INLINE Port open(); + template LIBC_INLINE Port open(); private: Process process; }; -static_assert(cpp::is_trivially_copyable::value && - sizeof(Process) == sizeof(Process), - "The client is not trivially copyable from the server"); /// The RPC server used to respond to the client. struct Server { @@ -366,7 +372,7 @@ struct Server { : process(port_count, buffer) {} using Port = rpc::Port; - LIBC_INLINE cpp::optional try_open(uint32_t lane_size, + LIBC_INLINE rpc::optional try_open(uint32_t lane_size, uint32_t start = 0); LIBC_INLINE Port open(uint32_t lane_size); @@ -450,7 +456,7 @@ LIBC_INLINE void Port::send_n(const void *const *src, uint64_t *size) { send([&](Buffer *buffer, uint32_t id) { reinterpret_cast(buffer->data)[0] = lane_value(size, id); num_sends = is_process_gpu() ? lane_value(size, id) - : cpp::max(lane_value(size, id), num_sends); + : rpc::max(lane_value(size, id), num_sends); uint64_t len = lane_value(size, id) > sizeof(Buffer::data) - sizeof(uint64_t) ? sizeof(Buffer::data) - sizeof(uint64_t) @@ -459,7 +465,7 @@ LIBC_INLINE void Port::send_n(const void *const *src, uint64_t *size) { }); uint64_t idx = sizeof(Buffer::data) - sizeof(uint64_t); uint64_t mask = process.header[index].mask; - while (gpu::ballot(mask, idx < num_sends)) { + while (rpc::ballot(mask, idx < num_sends)) { send([=](Buffer *buffer, uint32_t id) { uint64_t len = lane_value(size, id) - idx > sizeof(Buffer::data) ? sizeof(Buffer::data) @@ -483,7 +489,7 @@ LIBC_INLINE void Port::recv_n(void **dst, uint64_t *size, A &&alloc) { lane_value(dst, id) = reinterpret_cast(alloc(lane_value(size, id))); num_recvs = is_process_gpu() ? lane_value(size, id) - : cpp::max(lane_value(size, id), num_recvs); + : rpc::max(lane_value(size, id), num_recvs); uint64_t len = lane_value(size, id) > sizeof(Buffer::data) - sizeof(uint64_t) ? sizeof(Buffer::data) - sizeof(uint64_t) @@ -492,7 +498,7 @@ LIBC_INLINE void Port::recv_n(void **dst, uint64_t *size, A &&alloc) { }); uint64_t idx = sizeof(Buffer::data) - sizeof(uint64_t); uint64_t mask = process.header[index].mask; - while (gpu::ballot(mask, idx < num_recvs)) { + while (rpc::ballot(mask, idx < num_recvs)) { recv([=](Buffer *buffer, uint32_t id) { uint64_t len = lane_value(size, id) - idx > sizeof(Buffer::data) ? sizeof(Buffer::data) @@ -510,17 +516,16 @@ LIBC_INLINE void Port::recv_n(void **dst, uint64_t *size, A &&alloc) { /// port. Each port instance uses an associated \p opcode to tell the server /// what to do. The Client interface provides the appropriate lane size to the /// port using the platform's returned value. -template -[[clang::convergent]] LIBC_INLINE Client::Port Client::open() { +template LIBC_INLINE Client::Port Client::open() { // Repeatedly perform a naive linear scan for a port that can be opened to // send data. - for (uint32_t index = gpu::get_cluster_id();; ++index) { + for (uint32_t index = 0;; ++index) { // Start from the beginning if we run out of ports to check. if (index >= process.port_count) index = 0; // Attempt to acquire the lock on this index. - uint64_t lane_mask = gpu::get_lane_mask(); + uint64_t lane_mask = rpc::get_lane_mask(); if (!process.try_lock(lane_mask, index)) continue; @@ -534,22 +539,22 @@ template continue; } - if (gpu::is_first_lane(lane_mask)) { + if (rpc::is_first_lane(lane_mask)) { process.header[index].opcode = opcode; process.header[index].mask = lane_mask; } - gpu::sync_lane(lane_mask); - return Port(process, lane_mask, gpu::get_lane_size(), index, out); + rpc::sync_lane(lane_mask); + return Port(process, lane_mask, rpc::get_num_lanes(), index, out); } } /// Attempts to open a port to use as the server. The server can only open a /// port if it has a pending receive operation -[[clang::convergent]] LIBC_INLINE cpp::optional +LIBC_INLINE rpc::optional Server::try_open(uint32_t lane_size, uint32_t start) { // Perform a naive linear scan for a port that has a pending request. for (uint32_t index = start; index < process.port_count; ++index) { - uint64_t lane_mask = gpu::get_lane_mask(); + uint64_t lane_mask = rpc::get_lane_mask(); uint32_t in = process.load_inbox(lane_mask, index); uint32_t out = process.load_outbox(lane_mask, index); @@ -572,17 +577,27 @@ Server::try_open(uint32_t lane_size, uint32_t start) { return Port(process, lane_mask, lane_size, index, out); } - return cpp::nullopt; + return rpc::nullopt; } LIBC_INLINE Server::Port Server::open(uint32_t lane_size) { for (;;) { - if (cpp::optional p = try_open(lane_size)) - return cpp::move(p.value()); + if (rpc::optional p = try_open(lane_size)) + return rpc::move(p.value()); sleep_briefly(); } } +#if !__has_builtin(__scoped_atomic_load_n) +#undef __scoped_atomic_load_n +#undef __scoped_atomic_store_n +#undef __scoped_atomic_fetch_or +#undef __scoped_atomic_fetch_and +#endif +#if !__has_builtin(__scoped_atomic_thread_fence) +#undef __scoped_atomic_thread_fence +#endif + } // namespace rpc } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/RPC/rpc_client.h b/libc/src/__support/RPC/rpc_client.h index 695b6b7515bf7ba3cb4de73b6cdb859eff972516..7bd6d0b5e00b478fb9ccbefc92cd9f1f1ea42e13 100644 --- a/libc/src/__support/RPC/rpc_client.h +++ b/libc/src/__support/RPC/rpc_client.h @@ -12,11 +12,16 @@ #include "rpc.h" #include "include/llvm-libc-types/rpc_opcodes_t.h" +#include "src/__support/CPP/type_traits.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { namespace rpc { +static_assert(cpp::is_trivially_copyable::value && + sizeof(Process) == sizeof(Process), + "The client is not trivially copyable from the server"); + /// The libc client instance used to communicate with the server. extern Client client; diff --git a/libc/src/__support/RPC/rpc_util.h b/libc/src/__support/RPC/rpc_util.h index 1a29ed65577148cc369a1b2cf9775f6040261126..7067dfc974eb31f727f877a97a0c646b6becbd29 100644 --- a/libc/src/__support/RPC/rpc_util.h +++ b/libc/src/__support/RPC/rpc_util.h @@ -9,27 +9,230 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_RPC_RPC_UTIL_H #define LLVM_LIBC_SRC___SUPPORT_RPC_RPC_UTIL_H -#include "src/__support/CPP/type_traits.h" -#include "src/__support/GPU/utils.h" #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" -#include "src/__support/macros/properties/architectures.h" -#include "src/__support/threads/sleep.h" -#include "src/string/memory_utils/generic/byte_per_byte.h" -#include "src/string/memory_utils/inline_memcpy.h" + +#include +#include + +#if defined(__NVPTX__) || defined(__AMDGPU__) +#include +#define RPC_TARGET_IS_GPU +#endif namespace LIBC_NAMESPACE_DECL { namespace rpc { +template struct type_identity { + using type = T; +}; + +template struct type_constant { + static inline constexpr T value = v; +}; + +template struct remove_reference : type_identity {}; +template struct remove_reference : type_identity {}; +template struct remove_reference : type_identity {}; + +template struct is_const : type_constant {}; +template struct is_const : type_constant {}; + +/// Freestanding implementation of std::move. +template +LIBC_INLINE constexpr typename remove_reference::type &&move(T &&t) { + return static_cast::type &&>(t); +} + +/// Freestanding implementation of std::forward. +template +LIBC_INLINE constexpr T &&forward(typename remove_reference::type &value) { + return static_cast(value); +} +template +LIBC_INLINE constexpr T &&forward(typename remove_reference::type &&value) { + return static_cast(value); +} + +struct in_place_t { + LIBC_INLINE explicit in_place_t() = default; +}; + +struct nullopt_t { + LIBC_INLINE constexpr explicit nullopt_t() = default; +}; + +constexpr inline in_place_t in_place{}; +constexpr inline nullopt_t nullopt{}; + +/// Freestanding and minimal implementation of std::optional. +template class optional { + template struct OptionalStorage { + union { + char empty; + U stored_value; + }; + + bool in_use = false; + + LIBC_INLINE ~OptionalStorage() { reset(); } + + LIBC_INLINE constexpr OptionalStorage() : empty() {} + + template + LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args) + : stored_value(forward(args)...) {} + + LIBC_INLINE constexpr void reset() { + if (in_use) + stored_value.~U(); + in_use = false; + } + }; + + OptionalStorage storage; + +public: + LIBC_INLINE constexpr optional() = default; + LIBC_INLINE constexpr optional(nullopt_t) {} + + LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) { + storage.in_use = true; + } + LIBC_INLINE constexpr optional(const optional &) = default; + + LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) { + storage.in_use = true; + } + LIBC_INLINE constexpr optional(optional &&O) = default; + + LIBC_INLINE constexpr optional &operator=(T &&t) { + storage = move(t); + return *this; + } + LIBC_INLINE constexpr optional &operator=(optional &&) = default; + + LIBC_INLINE constexpr optional &operator=(const T &t) { + storage = t; + return *this; + } + LIBC_INLINE constexpr optional &operator=(const optional &) = default; + + LIBC_INLINE constexpr void reset() { storage.reset(); } + + LIBC_INLINE constexpr const T &value() const & { + return storage.stored_value; + } + + LIBC_INLINE constexpr T &value() & { return storage.stored_value; } + + LIBC_INLINE constexpr explicit operator bool() const { + return storage.in_use; + } + LIBC_INLINE constexpr bool has_value() const { return storage.in_use; } + LIBC_INLINE constexpr const T *operator->() const { + return &storage.stored_value; + } + LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; } + LIBC_INLINE constexpr const T &operator*() const & { + return storage.stored_value; + } + LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; } + + LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); } + LIBC_INLINE constexpr T &&operator*() && { + return move(storage.stored_value); + } +}; + +/// Suspend the thread briefly to assist the thread scheduler during busy loops. +LIBC_INLINE void sleep_briefly() { +#if defined(LIBC_TARGET_ARCH_IS_NVPTX) + if (__nvvm_reflect("__CUDA_ARCH") >= 700) + asm("nanosleep.u32 64;" ::: "memory"); +#elif defined(LIBC_TARGET_ARCH_IS_AMDGPU) + __builtin_amdgcn_s_sleep(2); +#elif defined(LIBC_TARGET_ARCH_IS_X86) + __builtin_ia32_pause(); +#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && __has_builtin(__builtin_arm_isb) + __builtin_arm_isb(0xf); +#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) + asm volatile("isb\n" ::: "memory"); +#else + // Simply do nothing if sleeping isn't supported on this platform. +#endif +} + /// Conditional to indicate if this process is running on the GPU. LIBC_INLINE constexpr bool is_process_gpu() { -#if defined(LIBC_TARGET_ARCH_IS_GPU) +#ifdef RPC_TARGET_IS_GPU return true; #else return false; #endif } +/// Wait for all lanes in the group to complete. +LIBC_INLINE void sync_lane(uint64_t lane_mask) { +#ifdef RPC_TARGET_IS_GPU + return __gpu_sync_lane(lane_mask); +#endif +} + +/// Copies the value from the first active thread to the rest. +LIBC_INLINE uint32_t broadcast_value(uint64_t lane_mask, uint32_t x) { +#ifdef RPC_TARGET_IS_GPU + return __gpu_read_first_lane_u32(lane_mask, x); +#else + return x; +#endif +} + +/// Returns the number lanes that participate in the RPC interface. +LIBC_INLINE uint32_t get_num_lanes() { +#ifdef RPC_TARGET_IS_GPU + return __gpu_num_lanes(); +#else + return 1; +#endif +} + +/// Returns the id of the thread inside of an AMD wavefront executing together. +LIBC_INLINE uint64_t get_lane_mask() { +#ifdef RPC_TARGET_IS_GPU + return __gpu_lane_mask(); +#else + return 1; +#endif +} + +/// Returns the id of the thread inside of an AMD wavefront executing together. +LIBC_INLINE uint32_t get_lane_id() { +#ifdef RPC_TARGET_IS_GPU + return __gpu_lane_id(); +#else + return 0; +#endif +} + +/// Conditional that is only true for a single thread in a lane. +LIBC_INLINE bool is_first_lane(uint64_t lane_mask) { +#ifdef RPC_TARGET_IS_GPU + return __gpu_is_first_in_lane(lane_mask); +#else + return true; +#endif +} + +/// Returns a bitmask of threads in the current lane for which \p x is true. +LIBC_INLINE uint64_t ballot(uint64_t lane_mask, bool x) { +#ifdef RPC_TARGET_IS_GPU + return __gpu_ballot(lane_mask, x); +#else + return x; +#endif +} + /// Return \p val aligned "upwards" according to \p align. template LIBC_INLINE constexpr V align_up(V val, A align) { @@ -48,7 +251,7 @@ template LIBC_INLINE V &lane_value(V *val, uint32_t id) { /// Advance the \p p by \p bytes. template LIBC_INLINE T *advance(T *ptr, U bytes) { - if constexpr (cpp::is_const_v) + if constexpr (is_const::value) return reinterpret_cast(reinterpret_cast(ptr) + bytes); else @@ -57,14 +260,11 @@ template LIBC_INLINE T *advance(T *ptr, U bytes) { /// Wrapper around the optimal memory copy implementation for the target. LIBC_INLINE void rpc_memcpy(void *dst, const void *src, size_t count) { - // The built-in memcpy prefers to fully unroll loops. We want to minimize - // resource usage so we use a single nounroll loop implementation. -#if defined(LIBC_TARGET_ARCH_IS_AMDGPU) - inline_memcpy_byte_per_byte(reinterpret_cast(dst), - reinterpret_cast(src), count); -#else - inline_memcpy(dst, src, count); -#endif + __builtin_memcpy(dst, src, count); +} + +template LIBC_INLINE constexpr const T &max(const T &a, const T &b) { + return (a < b) ? b : a; } } // namespace rpc diff --git a/libc/src/__support/big_int.h b/libc/src/__support/big_int.h index bea0abc84b213685cfe375715f80efd9623f112a..a95ab4ff8e1abf258e243e2e0d357de66bd7295e 100644 --- a/libc/src/__support/big_int.h +++ b/libc/src/__support/big_int.h @@ -469,7 +469,7 @@ public: !cpp::is_same_v>> LIBC_INLINE constexpr BigInt(T v) { constexpr size_t T_SIZE = sizeof(T) * CHAR_BIT; - const bool is_neg = Signed && (v < 0); + const bool is_neg = v < 0; for (size_t i = 0; i < WORD_COUNT; ++i) { if (v == 0) { extend(i, is_neg); @@ -504,6 +504,12 @@ public: // TODO: Reuse the Sign type. LIBC_INLINE constexpr bool is_neg() const { return SIGNED && get_msb(); } + template + LIBC_INLINE constexpr explicit + operator BigInt() const { + return BigInt(this); + } + template LIBC_INLINE constexpr explicit operator T() const { return to(); } @@ -1058,6 +1064,8 @@ struct WordTypeSelector : cpp::type_identity< // Except if we request 16 or 32 bits explicitly. template <> struct WordTypeSelector<16> : cpp::type_identity {}; template <> struct WordTypeSelector<32> : cpp::type_identity {}; +template <> struct WordTypeSelector<96> : cpp::type_identity {}; + template using WordTypeSelectorT = typename WordTypeSelector::type; } // namespace internal diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h index 48c773fa02c176c7d16a211f502ff60c12016ef1..79803a346f692e4104e956c16277278bde705f64 100644 --- a/libc/src/__support/common.h +++ b/libc/src/__support/common.h @@ -21,9 +21,25 @@ #define LLVM_LIBC_FUNCTION_ATTR #endif +// Allow each function `func` to have extra attributes specified by defining: +// `LLVM_LIBC_FUNCTION_ATTR_func` macro, which should always start with +// "LLVM_LIBC_EMPTY, " +// +// For examples: +// #define LLVM_LIBC_FUNCTION_ATTR_memcpy LLVM_LIBC_EMPTY, [[gnu::weak]] +// #define LLVM_LIBC_FUNCTION_ATTR_memchr LLVM_LIBC_EMPTY, [[gnu::weak]] \ +// [[gnu::visibility("default")]] +#define LLVM_LIBC_EMPTY + +#define GET_SECOND(first, second, ...) second +#define EXPAND_THEN_SECOND(name) GET_SECOND(name, LLVM_LIBC_EMPTY) + +#define LLVM_LIBC_ATTR(name) EXPAND_THEN_SECOND(LLVM_LIBC_FUNCTION_ATTR_##name) + // MacOS needs to be excluded because it does not support aliasing. #if defined(LIBC_COPT_PUBLIC_PACKAGING) && (!defined(__APPLE__)) #define LLVM_LIBC_FUNCTION_IMPL(type, name, arglist) \ + LLVM_LIBC_ATTR(name) \ LLVM_LIBC_FUNCTION_ATTR decltype(LIBC_NAMESPACE::name) \ __##name##_impl__ __asm__(#name); \ decltype(LIBC_NAMESPACE::name) name [[gnu::alias(#name)]]; \ diff --git a/libc/src/__support/endian.h b/libc/src/__support/endian_internal.h similarity index 96% rename from libc/src/__support/endian.h rename to libc/src/__support/endian_internal.h index 8c443fefab5e8fd7dcf22ff58c97283d15de4a1c..77839ad75455ba5ce6449d3268dedc6737f74c7f 100644 --- a/libc/src/__support/endian.h +++ b/libc/src/__support/endian_internal.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_ENDIAN_H -#define LLVM_LIBC_SRC___SUPPORT_ENDIAN_H +#ifndef LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H +#define LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H #include "common.h" #include "src/__support/macros/config.h" @@ -143,4 +143,4 @@ using Endian = internal::Endian<__BYTE_ORDER__>; } // namespace LIBC_NAMESPACE_DECL -#endif // LLVM_LIBC_SRC___SUPPORT_ENDIAN_H +#endif // LLVM_LIBC_SRC___SUPPORT_ENDIAN_INTERNAL_H diff --git a/libc/src/__support/float_to_string.h b/libc/src/__support/float_to_string.h index e2e06cd0492a90619f17401af98451bc205eda57..d5de6f38cb655756132d5044e45e559cf4c33320 100644 --- a/libc/src/__support/float_to_string.h +++ b/libc/src/__support/float_to_string.h @@ -373,23 +373,12 @@ LIBC_INLINE UInt get_table_negative_df(int exponent, size_t i) { return result; } -LIBC_INLINE uint32_t fast_uint_mod_1e9(const UInt &val) { - // The formula for mult_const is: - // 1 + floor((2^(bits in target integer size + log_2(divider))) / divider) - // Where divider is 10^9 and target integer size is 128. - const UInt mult_const( - {0x31680A88F8953031u, 0x89705F4136B4A597u, 0}); - const auto middle = (mult_const * val); - const uint64_t result = static_cast(middle[2]); - const uint64_t shifted = result >> 29; - return static_cast(static_cast(val) - - (EXP10_9 * shifted)); -} - LIBC_INLINE uint32_t mul_shift_mod_1e9(const FPBits::StorageType mantissa, const UInt &large, const int32_t shift_amount) { - UInt val(large); + // make sure the number of bits is always divisible by 64 + UInt val( + large); val = (val * mantissa) >> shift_amount; return static_cast( val.div_uint_half_times_pow_2(static_cast(EXP10_9), 0).value()); diff --git a/libc/src/__support/hash.h b/libc/src/__support/hash.h index 527c83993fd59a0a2c90f9b0086431380b95244c..49138b1f43b9edbc642b9a15b89cd375067a6c83 100644 --- a/libc/src/__support/hash.h +++ b/libc/src/__support/hash.h @@ -13,8 +13,8 @@ #include "src/__support/CPP/limits.h" // numeric_limits #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/config.h" -#include "src/__support/uint128.h" // UInt128 -#include // For uint64_t +#include "src/__support/uint128.h" // UInt128 +#include // For uint64_t namespace LIBC_NAMESPACE_DECL { namespace internal { @@ -34,25 +34,23 @@ LIBC_INLINE uint64_t folded_multiply(uint64_t x, uint64_t y) { // Therefore, we use a union to read the value. template LIBC_INLINE T read_little_endian(const void *ptr) { const uint8_t *bytes = static_cast(ptr); - union { - T value; - uint8_t buffer[sizeof(T)]; - } data; + uint8_t buffer[sizeof(T)]; #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ - // Compiler should able to optimize this as a load followed by a byte swap. - // On aarch64 (-mbig-endian), this compiles to the following for int: + // Compiler should able to optimize this as a load followed by a byte + // swap. On aarch64 (-mbig-endian), this compiles to the following for + // int: // ldr w0, [x0] // rev w0, w0 // ret for (size_t i = 0; i < sizeof(T); ++i) { - data.buffer[i] = bytes[sizeof(T) - i - 1]; + buffer[i] = bytes[sizeof(T) - i - 1]; } #else for (size_t i = 0; i < sizeof(T); ++i) { - data.buffer[i] = bytes[i]; + buffer[i] = bytes[i]; } #endif - return data.value; + return cpp::bit_cast(buffer); } // Specialized read functions for small values. size must be <= 8. diff --git a/libc/src/__support/high_precision_decimal.h b/libc/src/__support/high_precision_decimal.h index ac11649d1d1686ccc917542b4a7130c2e9f8496c..20088d6d79791047a144d5762c9004266e989388 100644 --- a/libc/src/__support/high_precision_decimal.h +++ b/libc/src/__support/high_precision_decimal.h @@ -350,7 +350,8 @@ public: if (!saw_dot) this->decimal_point = total_digits; - if (num_cur < num_len && ((num_string[num_cur] | 32) == 'e')) { + if (num_cur < num_len && + (num_string[num_cur] == 'e' || num_string[num_cur] == 'E')) { ++num_cur; if (isdigit(num_string[num_cur]) || num_string[num_cur] == '+' || num_string[num_cur] == '-') { diff --git a/libc/src/__support/integer_literals.h b/libc/src/__support/integer_literals.h index af3da1c443d7b72652bc0f0730b999a934997bcf..4c5c4c416668119f56b55d11b2a7aa9f343e3e89 100644 --- a/libc/src/__support/integer_literals.h +++ b/libc/src/__support/integer_literals.h @@ -165,6 +165,10 @@ LIBC_INLINE constexpr T parse_with_prefix(const char *ptr) { } // namespace internal +LIBC_INLINE constexpr UInt<96> operator""_u96(const char *x) { + return internal::parse_with_prefix>(x); +} + LIBC_INLINE constexpr UInt128 operator""_u128(const char *x) { return internal::parse_with_prefix(x); } diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index a1f4eef03fc3ce2aa267c8b1dea98a81d857f108..80ea334d15c03f3d23197f1a31210c3b97be1546 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -206,7 +206,7 @@ eisel_lemire(ExpandedFloat init_num, using FPBits = typename fputil::FPBits; using StorageType = typename FPBits::StorageType; - StorageType mantissa = init_num.mantissa; + UInt128 mantissa = init_num.mantissa; int32_t exp10 = init_num.exponent; // Exp10 Range @@ -225,7 +225,8 @@ eisel_lemire(ExpandedFloat init_num, } // Normalization - uint32_t clz = cpp::countl_zero(mantissa); + uint32_t clz = cpp::countl_zero(mantissa) - + ((sizeof(UInt128) - sizeof(StorageType)) * CHAR_BIT); mantissa <<= clz; int32_t exp2 = @@ -276,9 +277,8 @@ eisel_lemire(ExpandedFloat init_num, // Shifting to 65 bits for 80 bit floats and 113 bits for 128 bit floats uint32_t msb = static_cast(final_approx_upper >> (FPBits::STORAGE_LEN - 1)); - StorageType final_mantissa = - final_approx_upper >> - (msb + FPBits::STORAGE_LEN - (FPBits::FRACTION_LEN + 3)); + UInt128 final_mantissa = final_approx_upper >> (msb + FPBits::STORAGE_LEN - + (FPBits::FRACTION_LEN + 3)); exp2 -= static_cast(1 ^ msb); // same as !msb if (round == RoundDirection::Nearest) { @@ -315,7 +315,7 @@ eisel_lemire(ExpandedFloat init_num, } ExpandedFloat output; - output.mantissa = final_mantissa; + output.mantissa = static_cast(final_mantissa); output.exponent = exp2; return output; } @@ -558,7 +558,7 @@ clinger_fast_path(ExpandedFloat init_num, FPBits result; T float_mantissa; - if constexpr (cpp::is_same_v>) { + if constexpr (is_big_int_v || sizeof(T) > sizeof(uint64_t)) { float_mantissa = (static_cast(uint64_t(mantissa >> 64)) * static_cast(0x1.0p64)) + static_cast(uint64_t(mantissa)); diff --git a/libc/src/math/generic/exp10m1f16.cpp b/libc/src/math/generic/exp10m1f16.cpp index 9f2c1959fa5ec99dc695c1df335efde65f98c354..449aedf254ca500c19764de5744b3fb58ec09d23 100644 --- a/libc/src/math/generic/exp10m1f16.cpp +++ b/libc/src/math/generic/exp10m1f16.cpp @@ -119,6 +119,9 @@ LLVM_LIBC_FUNCTION(float16, exp10m1f16, (float16 x)) { // When |x| <= 2^(-3). if (x_abs <= 0x3000U) { + if (LIBC_UNLIKELY(x_abs == 0)) + return x; + if (auto r = EXP10M1F16_EXCEPTS_LO.lookup(x_u); LIBC_UNLIKELY(r.has_value())) return r.value(); diff --git a/libc/src/math/generic/tanhf16.cpp b/libc/src/math/generic/tanhf16.cpp index ae9b4be46f7cff5d3ffda96ef8a91824e999b93b..0266b5cfc2df1d9f086eb23edddfe936be225790 100644 --- a/libc/src/math/generic/tanhf16.cpp +++ b/libc/src/math/generic/tanhf16.cpp @@ -64,6 +64,9 @@ LLVM_LIBC_FUNCTION(float16, tanhf16, (float16 x)) { // When |x| <= 0x1.d2p-4. if (x_abs <= 0x2f48U) { + if (LIBC_UNLIKELY(x_abs == 0)) + return x; + float xf = x; float xf_sq = xf * xf; // Degree-7 Taylor expansion generated by Sollya with the following diff --git a/libc/src/network/htonl.cpp b/libc/src/network/htonl.cpp index ec3c02e2894f2fc7b8b29765fd9ce34323198ce2..681786adea68a70c97906908e480a76d689580bb 100644 --- a/libc/src/network/htonl.cpp +++ b/libc/src/network/htonl.cpp @@ -8,7 +8,7 @@ #include "src/network/htonl.h" #include "src/__support/common.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/network/htons.cpp b/libc/src/network/htons.cpp index 78416b3a7d1f0a8f159ad2803c8f100850fb56d9..675f53cf4a0ad696a49adf22cbb3ae0b2c4a378b 100644 --- a/libc/src/network/htons.cpp +++ b/libc/src/network/htons.cpp @@ -8,7 +8,7 @@ #include "src/network/htons.h" #include "src/__support/common.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/network/ntohl.cpp b/libc/src/network/ntohl.cpp index 974b574432ff3d077b77b2fa65e3051819703d9e..6a309e97fca79b48e57139d56374ecac924a3802 100644 --- a/libc/src/network/ntohl.cpp +++ b/libc/src/network/ntohl.cpp @@ -8,7 +8,7 @@ #include "src/network/ntohl.h" #include "src/__support/common.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/network/ntohs.cpp b/libc/src/network/ntohs.cpp index bb1779f3dcb30c3cf8a07f34519cb877f7ec195a..b51ecb93241cac841a8b680fceb81197265df499 100644 --- a/libc/src/network/ntohs.cpp +++ b/libc/src/network/ntohs.cpp @@ -8,7 +8,7 @@ #include "src/network/ntohs.h" #include "src/__support/common.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/stdio/gpu/file.h b/libc/src/stdio/gpu/file.h index 16d64e8f37750182420e5ad3a84bfb326c7bc90a..6ca792b4545806dff9eeaa1ccdceec0851cd498f 100644 --- a/libc/src/stdio/gpu/file.h +++ b/libc/src/stdio/gpu/file.h @@ -49,7 +49,7 @@ LIBC_INLINE ::FILE *to_stream(uintptr_t f) { return stream; } -template +template LIBC_INLINE uint64_t write_impl(::FILE *file, const void *data, size_t size) { uint64_t ret = 0; rpc::Client::Port port = rpc::client.open(); diff --git a/libc/src/stdio/gpu/vfprintf_utils.h b/libc/src/stdio/gpu/vfprintf_utils.h index 5010ee16d96074abe1264159e3c18de1b1e3c78e..a0a8c39781ad69b0d91d894022dfcd34df85bc7f 100644 --- a/libc/src/stdio/gpu/vfprintf_utils.h +++ b/libc/src/stdio/gpu/vfprintf_utils.h @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "hdr/types/FILE.h" +#include "src/__support/GPU/utils.h" #include "src/__support/RPC/rpc_client.h" #include "src/__support/arg_list.h" #include "src/__support/macros/config.h" @@ -15,7 +16,7 @@ namespace LIBC_NAMESPACE_DECL { -template +template LIBC_INLINE int vfprintf_impl(::FILE *__restrict file, const char *__restrict format, size_t format_size, va_list vlist) { diff --git a/libc/src/stdlib/gpu/abort.cpp b/libc/src/stdlib/gpu/abort.cpp index cfc7e9b8e228bad1b77f98c4adcc72dfe77327c6..3a06fb38c3f64f8b1ce9bc4a3d872c85a52e1042 100644 --- a/libc/src/stdlib/gpu/abort.cpp +++ b/libc/src/stdlib/gpu/abort.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/GPU/utils.h" #include "src/__support/RPC/rpc_client.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" diff --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h index 89bbea8a2bdd2b64ee8aad60334cdf3d4ab1c1c1..da20a84dede4d14b165306734bd6b8e78aab0430 100644 --- a/libc/src/string/memory_utils/op_generic.h +++ b/libc/src/string/memory_utils/op_generic.h @@ -26,7 +26,7 @@ #include "src/__support/CPP/array.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" #include "src/__support/macros/optimization.h" #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h index 5e5fe593cce773863492ddab4db1be99ec57bad7..cae65bddd92f6e920436e9df736a14f69f11154a 100644 --- a/libc/src/string/memory_utils/utils.h +++ b/libc/src/string/memory_utils/utils.h @@ -12,7 +12,7 @@ #include "src/__support/CPP/bit.h" #include "src/__support/CPP/cstddef.h" #include "src/__support/CPP/type_traits.h" -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/config.h" #include "src/__support/macros/properties/architectures.h" diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp index ad5722f99a4369d10afe124fce964c6d0991f4bb..afb1368f0090505909026e28ead35c2270b8a3a1 100644 --- a/libc/test/UnitTest/LibcTest.cpp +++ b/libc/test/UnitTest/LibcTest.cpp @@ -44,7 +44,6 @@ cpp::enable_if_t<(cpp::is_integral_v && (sizeof(T) > sizeof(uint64_t))) || is_big_int_v, cpp::string> describeValue(T Value) { - static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); const IntegerToString buffer(Value); return buffer.view(); } @@ -242,6 +241,7 @@ TEST_SPECIALIZATION(__uint128_t); TEST_SPECIALIZATION(LIBC_NAMESPACE::Int<128>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<96>); TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<128>); TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<192>); TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<256>); diff --git a/libc/test/integration/scudo/CMakeLists.txt b/libc/test/integration/scudo/CMakeLists.txt index a5f7e3b63d24c37195a690855b87df839997dba7..b4011e501b96b3c96ee7750f6e7a8f3ccb3471c3 100644 --- a/libc/test/integration/scudo/CMakeLists.txt +++ b/libc/test/integration/scudo/CMakeLists.txt @@ -13,14 +13,23 @@ endif() add_entrypoint_library( libc_for_scudo_integration_test DEPENDS - libc.src.stdlib.malloc - libc.src.stdlib.calloc - libc.src.stdlib.realloc + libc.src.errno.errno + libc.src.fcntl.open + libc.src.sched.__sched_getcpucount libc.src.stdlib.aligned_alloc + libc.src.stdlib.calloc libc.src.stdlib.free - libc.src.errno.errno + libc.src.stdlib.malloc + libc.src.stdlib.realloc + libc.src.sys.auxv.getauxval + libc.src.sys.mman.mmap + libc.src.sys.mman.munmap + libc.src.sys.prctl.prctl libc.src.unistd.__llvm_libc_syscall - libc.src.sched.__sched_getcpucount + libc.src.unistd.close + libc.src.unistd.read + libc.src.unistd.sysconf + libc.src.unistd.write ) add_executable( diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt index 7ad262d5f1f3007a8f5b239cd9589f71b81608b0..c3a7d87d8281f93338430a18a84dba157a6cbc5a 100644 --- a/libc/test/src/__support/CMakeLists.txt +++ b/libc/test/src/__support/CMakeLists.txt @@ -1,6 +1,6 @@ add_custom_target(libc-support-tests) -if(NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX) +if(NOT LIBC_TARGET_OS_IS_GPU) add_libc_test( block_test SUITE @@ -57,11 +57,11 @@ add_libc_test( ) add_libc_test( - endian_test + endian_internal_test SUITE libc-support-tests SRCS - endian_test.cpp + endian_internal_test.cpp DEPENDS libc.src.__support.common ) diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp index bcab0286480c35cf4306cad3e374d13d0a798a28..6953d3aace58f395d1ab5cac87f74a96560fd58d 100644 --- a/libc/test/src/__support/FPUtil/fpbits_test.cpp +++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp @@ -8,12 +8,14 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/fpbits_str.h" +#include "src/__support/big_int.h" #include "src/__support/integer_literals.h" #include "src/__support/macros/properties/types.h" #include "src/__support/sign.h" // Sign #include "test/UnitTest/Test.h" using LIBC_NAMESPACE::Sign; +using LIBC_NAMESPACE::UInt; using LIBC_NAMESPACE::fputil::FPBits; using LIBC_NAMESPACE::fputil::FPType; using LIBC_NAMESPACE::fputil::internal::FPRep; @@ -21,6 +23,7 @@ using LIBC_NAMESPACE::fputil::internal::FPRep; using LIBC_NAMESPACE::operator""_u16; using LIBC_NAMESPACE::operator""_u32; using LIBC_NAMESPACE::operator""_u64; +using LIBC_NAMESPACE::operator""_u96; using LIBC_NAMESPACE::operator""_u128; TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary16) { @@ -121,9 +124,11 @@ TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary128) { UInt128(Rep::quiet_nan())); } +#ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) { using Rep = FPRep; +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ( 0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u128, UInt128(Rep::zero())); @@ -151,11 +156,43 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) { EXPECT_EQ( 0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u128, UInt128(Rep::quiet_nan())); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ( + 0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::zero())); + EXPECT_EQ( + 0b0'0111111111111111000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::one())); + EXPECT_EQ( + 0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000001_u96, + UInt<96>(Rep::min_subnormal())); + EXPECT_EQ( + 0b0'0000000000000000111111111111111111111111111111111111111111111111111111111111111_u96, + UInt<96>(Rep::max_subnormal())); + EXPECT_EQ( + 0b0'0000000000000011000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::min_normal())); + EXPECT_EQ( + 0b0'1111111111111101111111111111111111111111111111111111111111111111111111111111111_u96, + UInt<96>(Rep::max_normal())); + EXPECT_EQ( + 0b0'1111111111111111000000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::inf())); + EXPECT_EQ( + 0b0'1111111111111111010000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::signaling_nan())); + EXPECT_EQ( + 0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u96, + UInt<96>(Rep::quiet_nan())); +#else +#error "unhandled long double type" +#endif } TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) { using Rep = FPRep; +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_TRUE( // NAN : Pseudo-Infinity Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u128) .is_nan()); @@ -192,7 +229,48 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) { EXPECT_FALSE( // Normalized Rep(0b0'111111111111110'1000000000000000000000000000000000000000000000000000000000000000_u128) .is_nan()); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_TRUE( // NAN : Pseudo-Infinity + Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Pseudo Not a Number + Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Pseudo Not a Number + Rep(0b0'111111111111111'0100000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Signalling Not a Number + Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Floating-point Indefinite + Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Quiet Not a Number + Rep(0b0'111111111111111'1100000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_TRUE( // NAN : Unnormal + Rep(0b0'111111111111110'0000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_FALSE( // Zero + Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_FALSE( // Subnormal + Rep(0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_FALSE( // Pseudo Denormal + Rep(0b0'000000000000000'1000000000000000000000000000000000000000000000000000000000000001_u96) + .is_nan()); + EXPECT_FALSE( // Infinity + Rep(0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); + EXPECT_FALSE( // Normalized + Rep(0b0'111111111111110'1000000000000000000000000000000000000000000000000000000000000000_u96) + .is_nan()); +#else +#error "unhandled long double type" +#endif } +#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 enum class FP { ZERO, @@ -430,6 +508,7 @@ TEST(LlvmLibcFPBitsTest, DoubleType) { #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { using LongDoubleBits = FPBits; + using Rep = FPRep; EXPECT_STREQ(LIBC_NAMESPACE::str(LongDoubleBits::inf(Sign::POS)).c_str(), "(+Infinity)"); @@ -441,62 +520,117 @@ TEST(LlvmLibcFPBitsTest, X86LongDoubleType) { LongDoubleBits zero(0.0l); EXPECT_TRUE(zero.is_pos()); EXPECT_EQ(zero.get_biased_exponent(), 0_u16); - EXPECT_EQ(zero.get_mantissa(), 0_u128); - EXPECT_EQ(zero.uintval(), 0_u128); + EXPECT_EQ(zero.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); + EXPECT_EQ(zero.uintval(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_STREQ( LIBC_NAMESPACE::str(zero).c_str(), "0x00000000000000000000000000000000 = " "(S: 0, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_STREQ(LIBC_NAMESPACE::str(zero).c_str(), + "0x000000000000000000000000 = " + "(S: 0, E: 0x0000, I: 0, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits negzero(-0.0l); EXPECT_TRUE(negzero.is_neg()); EXPECT_EQ(negzero.get_biased_exponent(), 0_u16); - EXPECT_EQ(negzero.get_mantissa(), 0_u128); + EXPECT_EQ(negzero.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(negzero.uintval(), 0x8000'00000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(negzero).c_str(), "0x00000000000080000000000000000000 = " "(S: 1, E: 0x0000, I: 0, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(negzero.uintval(), 0x8000'00000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(negzero).c_str(), + "0x000080000000000000000000 = " + "(S: 1, E: 0x0000, I: 0, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits one(1.0l); EXPECT_TRUE(one.is_pos()); EXPECT_EQ(one.get_biased_exponent(), 0x3FFF_u16); - EXPECT_EQ(one.get_mantissa(), 0_u128); + EXPECT_EQ(one.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(one.uintval(), 0x3FFF'80000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(one).c_str(), "0x0000000000003FFF8000000000000000 = " "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(one.uintval(), 0x3FFF'80000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(one).c_str(), + "0x00003FFF8000000000000000 = " + "(S: 0, E: 0x3FFF, I: 1, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits negone(-1.0l); EXPECT_TRUE(negone.is_neg()); EXPECT_EQ(negone.get_biased_exponent(), 0x3FFF_u16); - EXPECT_EQ(negone.get_mantissa(), 0_u128); + EXPECT_EQ(negone.get_mantissa(), LongDoubleBits::StorageType(Rep::zero())); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(negone.uintval(), 0xBFFF'80000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(negone).c_str(), "0x000000000000BFFF8000000000000000 = " "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000000000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(negone.uintval(), 0xBFFF'80000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(negone).c_str(), + "0x0000BFFF8000000000000000 = " + "(S: 1, E: 0x3FFF, I: 1, M: 0x000000000000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits num(1.125l); EXPECT_TRUE(num.is_pos()); EXPECT_EQ(num.get_biased_exponent(), 0x3FFF_u16); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(num.get_mantissa(), 0x10000000'00000000_u128); EXPECT_EQ(num.uintval(), 0x3FFF'90000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(num).c_str(), "0x0000000000003FFF9000000000000000 = " "(S: 0, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(num.get_mantissa(), 0x10000000'00000000_u96); + EXPECT_EQ(num.uintval(), 0x3FFF'90000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(num).c_str(), + "0x00003FFF9000000000000000 = " + "(S: 0, E: 0x3FFF, I: 1, M: 0x000000001000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits negnum(-1.125l); EXPECT_TRUE(negnum.is_neg()); EXPECT_EQ(negnum.get_biased_exponent(), 0x3FFF_u16); +#if __SIZEOF_LONG_DOUBLE__ == 16 EXPECT_EQ(negnum.get_mantissa(), 0x10000000'00000000_u128); EXPECT_EQ(negnum.uintval(), 0xBFFF'90000000'00000000_u128); EXPECT_STREQ( LIBC_NAMESPACE::str(negnum).c_str(), "0x000000000000BFFF9000000000000000 = " "(S: 1, E: 0x3FFF, I: 1, M: 0x00000000000000001000000000000000)"); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + EXPECT_EQ(negnum.get_mantissa(), 0x10000000'00000000_u96); + EXPECT_EQ(negnum.uintval(), 0xBFFF'90000000'00000000_u96); + EXPECT_STREQ(LIBC_NAMESPACE::str(negnum).c_str(), + "0x0000BFFF9000000000000000 = " + "(S: 1, E: 0x3FFF, I: 1, M: 0x000000001000000000000000)"); +#else +#error "unhandled long double type" +#endif LongDoubleBits quiet_nan = LongDoubleBits::quiet_nan(); EXPECT_EQ(quiet_nan.is_quiet_nan(), true); diff --git a/libc/test/src/__support/HashTable/group_test.cpp b/libc/test/src/__support/HashTable/group_test.cpp index 25b15312ad6680a38b01b36cb02737e4cc48d204..acdc58e205852a80d7499326fd85cb29dbde9b54 100644 --- a/libc/test/src/__support/HashTable/group_test.cpp +++ b/libc/test/src/__support/HashTable/group_test.cpp @@ -8,6 +8,7 @@ #include "src/__support/HashTable/bitmask.h" +#include "src/__support/CPP/bit.h" #include "src/__support/macros/config.h" #include "src/stdlib/rand.h" #include "test/UnitTest/Test.h" @@ -28,14 +29,13 @@ TEST(LlvmLibcHashTableBitMaskTest, Match) { size_t appearance[4][sizeof(Group)]; ByteArray array{}; - union { - uintptr_t random; - int data[sizeof(uintptr_t) / sizeof(int)]; - }; + int data[sizeof(uintptr_t) / sizeof(int)]; for (int &i : data) i = rand(); + uintptr_t random = cpp::bit_cast(data); + for (size_t i = 0; i < sizeof(Group); ++i) { size_t choice = random % 4; random /= 4; @@ -62,14 +62,13 @@ TEST(LlvmLibcHashTableBitMaskTest, MaskAvailable) { for (size_t i = 0; i < sizeof(Group); ++i) { ByteArray array{}; - union { - uintptr_t random; - int data[sizeof(uintptr_t) / sizeof(int)]; - }; + int data[sizeof(uintptr_t) / sizeof(int)]; for (int &j : data) j = rand(); + uintptr_t random = cpp::bit_cast(data); + ASSERT_FALSE(Group::load(array.data).mask_available().any_bit_set()); array.data[i] = 0x80; diff --git a/libc/test/src/__support/HashTable/table_test.cpp b/libc/test/src/__support/HashTable/table_test.cpp index f8ffa4d4123d35702117a873ce88c37fc7f8a596..c3b8697f2087a10a2905b1b3f97d9816f39fcde5 100644 --- a/libc/test/src/__support/HashTable/table_test.cpp +++ b/libc/test/src/__support/HashTable/table_test.cpp @@ -82,7 +82,7 @@ TEST(LlvmLibcTableTest, GrowthSequence) { } TEST(LlvmLibcTableTest, Insertion) { - union key { + struct key { char bytes[2]; } keys[256]; for (size_t k = 0; k < 256; ++k) { diff --git a/libc/test/src/__support/big_int_test.cpp b/libc/test/src/__support/big_int_test.cpp index 471ca72a8f6e0c8764049e12a8964beac4eec9c1..2666ed978dad7abab4b9224fa65d79f60aca84bb 100644 --- a/libc/test/src/__support/big_int_test.cpp +++ b/libc/test/src/__support/big_int_test.cpp @@ -1067,4 +1067,12 @@ TEST(LlvmLibcUIntClassTest, SignedOtherWordTypeCastTests) { ASSERT_TRUE(bigger_back_plus_a + bigger_back_minus_a == zero_96); } +TEST(LlvmLibcUIntClassTest, MixedSignednessOtherWordTypeCastTests) { + using LL_UInt96 = BigInt<96, false, uint32_t>; + LL_UInt96 x = -123; + // ensure that -123 gets extended, even though the input type is signed while + // the BigInt is unsigned. + ASSERT_EQ(int64_t(x), int64_t(-123)); +} + } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/__support/endian_test.cpp b/libc/test/src/__support/endian_internal_test.cpp similarity index 97% rename from libc/test/src/__support/endian_test.cpp rename to libc/test/src/__support/endian_internal_test.cpp index 758c13b686946ae9e202322a2d36012478163d7c..eab0f376e749560dda5284f1922f5061593db1f1 100644 --- a/libc/test/src/__support/endian_test.cpp +++ b/libc/test/src/__support/endian_internal_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/__support/macros/config.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/__support/str_to_long_double_test.cpp b/libc/test/src/__support/str_to_long_double_test.cpp index 9efa457aac95776fff97acc85b2ab130c8eeaf41..fa7d600f9bff4e59a2cf0c8e9915dc64fb18ef55 100644 --- a/libc/test/src/__support/str_to_long_double_test.cpp +++ b/libc/test/src/__support/str_to_long_double_test.cpp @@ -30,12 +30,23 @@ TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80Simple) { } TEST_F(LlvmLibcStrToLongDblTest, EiselLemireFloat80LongerMantissa) { +#if __SIZEOF_LONG_DOUBLE__ == 16 eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 0, 0x91a2b3c091a2b3c1, 16507); eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, 300, 0xd97757de56adb65c, 17503); eisel_lemire_test(0x12345678'12345678'12345678'12345678_u128, -300, 0xc30feb9a7618457d, 15510); +#elif __SIZEOF_LONG_DOUBLE__ == 12 + eisel_lemire_test(0x12345678'12345678'12345678_u96, 0, 0x91a2b3c091a2b3c1, + 16475); + eisel_lemire_test(0x12345678'12345678'12345678_u96, 300, 0xd97757de56adb65c, + 17471); + eisel_lemire_test(0x12345678'12345678'12345678_u96, -300, 0xc30feb9a7618457d, + 15478); +#else +#error "unhandled long double type" +#endif } // These tests check numbers at the edge of the DETAILED_POWERS_OF_TEN table. diff --git a/libc/test/src/math/smoke/CanonicalizeTest.h b/libc/test/src/math/smoke/CanonicalizeTest.h index 3baf60c3140ff4dcfe7dfa36e5c5895f2b5f88d8..ef75f568b8275b6018bf696ce9d407951b666d29 100644 --- a/libc/test/src/math/smoke/CanonicalizeTest.h +++ b/libc/test/src/math/smoke/CanonicalizeTest.h @@ -25,6 +25,7 @@ #define TEST_REGULAR(x, y, expected) TEST_SPECIAL(x, y, expected, 0) +using LIBC_NAMESPACE::operator""_u96; using LIBC_NAMESPACE::operator""_u128; template @@ -61,7 +62,11 @@ public: // Exponent | Significand | Meaning // | Bits 63-62 | Bits 61-0 | // All Ones | 00 | Zero | Pseudo Infinity, Value = SNaN +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test1(0x00007FFF'00000000'00000000_u96); +#else FPBits test1(0x00000000'00007FFF'00000000'00000000_u128); +#endif const T test1_val = test1.get_val(); TEST_SPECIAL(cx, test1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); @@ -69,22 +74,38 @@ public: // Exponent | Significand | Meaning // | Bits 63-62 | Bits 61-0 | // All Ones | 00 | Non-Zero | Pseudo NaN, Value = SNaN +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_1(0x00007FFF'00000000'00000001_u96); +#else FPBits test2_1(0x00000000'00007FFF'00000000'00000001_u128); +#endif const T test2_1_val = test2_1.get_val(); TEST_SPECIAL(cx, test2_1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_2(0x00007FFF'00000042'70000001_u96); +#else FPBits test2_2(0x00000000'00007FFF'00000042'70000001_u128); +#endif const T test2_2_val = test2_2.get_val(); TEST_SPECIAL(cx, test2_2_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_3(0x00007FFF'00000000'08261001_u96); +#else FPBits test2_3(0x00000000'00007FFF'00000000'08261001_u128); +#endif const T test2_3_val = test2_3.get_val(); TEST_SPECIAL(cx, test2_3_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test2_4(0x00007FFF'00007800'08261001_u96); +#else FPBits test2_4(0x00000000'00007FFF'00007800'08261001_u128); +#endif const T test2_4_val = test2_4.get_val(); TEST_SPECIAL(cx, test2_4_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); @@ -92,22 +113,38 @@ public: // Exponent | Significand | Meaning // | Bits 63-62 | Bits 61-0 | // All Ones | 01 | Anything | Pseudo NaN, Value = SNaN +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_1(0x00007FFF'40000000'00000000_u96); +#else FPBits test3_1(0x00000000'00007FFF'40000000'00000000_u128); +#endif const T test3_1_val = test3_1.get_val(); TEST_SPECIAL(cx, test3_1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_2(0x00007FFF'40000042'70000001_u96); +#else FPBits test3_2(0x00000000'00007FFF'40000042'70000001_u128); +#endif const T test3_2_val = test3_2.get_val(); TEST_SPECIAL(cx, test3_2_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_3(0x00007FFF'40000000'08261001_u96); +#else FPBits test3_3(0x00000000'00007FFF'40000000'08261001_u128); +#endif const T test3_3_val = test3_3.get_val(); TEST_SPECIAL(cx, test3_3_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test3_4(0x00007FFF'40007800'08261001_u96); +#else FPBits test3_4(0x00000000'00007FFF'40007800'08261001_u128); +#endif const T test3_4_val = test3_4.get_val(); TEST_SPECIAL(cx, test3_4_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); @@ -116,19 +153,31 @@ public: // | Bit 63 | Bits 62-0 | // All zeroes | One | Anything | Pseudo Denormal, Value = // | | | (−1)**s × m × 2**−16382 +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test4_1(0x00000000'80000000'00000000_u96); +#else FPBits test4_1(0x00000000'00000000'80000000'00000000_u128); +#endif const T test4_1_val = test4_1.get_val(); TEST_SPECIAL(cx, test4_1_val, 0, 0); EXPECT_FP_EQ( cx, FPBits::make_value(test4_1.get_explicit_mantissa(), 0).get_val()); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test4_2(0x00000000'80000042'70000001_u96); +#else FPBits test4_2(0x00000000'00000000'80000042'70000001_u128); +#endif const T test4_2_val = test4_2.get_val(); TEST_SPECIAL(cx, test4_2_val, 0, 0); EXPECT_FP_EQ( cx, FPBits::make_value(test4_2.get_explicit_mantissa(), 0).get_val()); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test4_3(0x00000000'80000000'08261001_u96); +#else FPBits test4_3(0x00000000'00000000'80000000'08261001_u128); +#endif const T test4_3_val = test4_3.get_val(); TEST_SPECIAL(cx, test4_3_val, 0, 0); EXPECT_FP_EQ( @@ -138,32 +187,56 @@ public: // | Bit 63 | Bits 62-0 | // All Other | Zero | Anything | Unnormal, Value = SNaN // Values | | | +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_1(0x00000040'00000000'00000001_u96); +#else FPBits test5_1(0x00000000'00000040'00000000'00000001_u128); +#endif const T test5_1_val = test5_1.get_val(); TEST_SPECIAL(cx, test5_1_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_2(0x00000230'00000042'70000001_u96); +#else FPBits test5_2(0x00000000'00000230'00000042'70000001_u128); +#endif const T test5_2_val = test5_2.get_val(); TEST_SPECIAL(cx, test5_2_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_3(0x00000560'00000000'08261001_u96); +#else FPBits test5_3(0x00000000'00000560'00000000'08261001_u128); +#endif const T test5_3_val = test5_3.get_val(); TEST_SPECIAL(cx, test5_3_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_4(0x00000780'00000028'16000000_u96); +#else FPBits test5_4(0x00000000'00000780'00000028'16000000_u128); +#endif const T test5_4_val = test5_4.get_val(); TEST_SPECIAL(cx, test5_4_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_5(0x00000900'00000042'70000001_u96); +#else FPBits test5_5(0x00000000'00000900'00000042'70000001_u128); +#endif const T test5_5_val = test5_5.get_val(); TEST_SPECIAL(cx, test5_5_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); +#if __SIZEOF_LONG_DOUBLE__ == 12 + FPBits test5_6(0x00000AB0'00000000'08261001_u96); +#else FPBits test5_6(0x00000000'00000AB0'00000000'08261001_u128); +#endif const T test5_6_val = test5_6.get_val(); TEST_SPECIAL(cx, test5_6_val, 1, FE_INVALID); EXPECT_FP_EQ(cx, aNaN); diff --git a/libc/test/src/network/htonl_test.cpp b/libc/test/src/network/htonl_test.cpp index d3b930d0b1ea24c416dceaa7d20f5dd68e53b22c..f2e2541312c31ab6e3ca63c321137fd2fd829dfb 100644 --- a/libc/test/src/network/htonl_test.cpp +++ b/libc/test/src/network/htonl_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/network/htonl.h" #include "src/network/ntohl.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/network/htons_test.cpp b/libc/test/src/network/htons_test.cpp index d38fab8153b97c70bcdbef49c4a709a62b17b10a..9668162523ce5df97cd9ad4e453e962b220ba3dd 100644 --- a/libc/test/src/network/htons_test.cpp +++ b/libc/test/src/network/htons_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/network/htons.h" #include "src/network/ntohs.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/network/ntohl_test.cpp b/libc/test/src/network/ntohl_test.cpp index b06f8e19e4f45bd6a233eaec4d14dc29c56802a6..b72456b7200e58477711d87c49eb52923634fa0a 100644 --- a/libc/test/src/network/ntohl_test.cpp +++ b/libc/test/src/network/ntohl_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/network/htonl.h" #include "src/network/ntohl.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/network/ntohs_test.cpp b/libc/test/src/network/ntohs_test.cpp index 654a39662ac9ce1d6a941d95337fd1e29662b351..1104356076b94b0d8254056be49538de73b7b7c9 100644 --- a/libc/test/src/network/ntohs_test.cpp +++ b/libc/test/src/network/ntohs_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/endian.h" +#include "src/__support/endian_internal.h" #include "src/network/htons.h" #include "src/network/ntohs.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/stdlib/strtold_test.cpp b/libc/test/src/stdlib/strtold_test.cpp index 2c9f542930bf8636301ccb12dcaf70253b5175a7..b209c85b88e3692feb8fd9da93dd1c3a537af3cf 100644 --- a/libc/test/src/stdlib/strtold_test.cpp +++ b/libc/test/src/stdlib/strtold_test.cpp @@ -75,8 +75,9 @@ public: // +-- 15 Exponent Bits char *str_end = nullptr; - LIBC_NAMESPACE::fputil::FPBits expected_fp = - LIBC_NAMESPACE::fputil::FPBits(expectedRawData); + using FPBits = LIBC_NAMESPACE::fputil::FPBits; + FPBits expected_fp = + FPBits(static_cast(expectedRawData)); const int expected_errno = expectedErrno; LIBC_NAMESPACE::libc_errno = 0; diff --git a/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp b/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp index 9daac13321cd43d370b96b0f5e723520f4a25a64..f4d71e906e2ad825c40464f1cf0adcba7727045d 100644 --- a/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp +++ b/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp @@ -33,9 +33,13 @@ TEST(LlvmLibcSysFStatvfsTest, FStatvfsBasic) { TEST(LlvmLibcSysFStatvfsTest, FStatvfsInvalidPath) { struct statvfs buf; - constexpr const char *FILENAME = "statvfs.testdir"; + constexpr const char *FILENAME = "fstatvfs.testdir"; auto TEST_DIR = libc_make_test_file_path(FILENAME); + // Always delete the folder so that we start in a consistent state. + LIBC_NAMESPACE::rmdir(TEST_DIR); + LIBC_NAMESPACE::libc_errno = 0; // Reset errno + ASSERT_THAT(LIBC_NAMESPACE::mkdirat(AT_FDCWD, TEST_DIR, S_IRWXU), Succeeds(0)); diff --git a/libc/test/src/sys/statvfs/linux/statvfs_test.cpp b/libc/test/src/sys/statvfs/linux/statvfs_test.cpp index 68448e0530af8463913294d7775f823d292d0a78..32f8120e17b42e8e222ec2f6183085b2f66a7c6c 100644 --- a/libc/test/src/sys/statvfs/linux/statvfs_test.cpp +++ b/libc/test/src/sys/statvfs/linux/statvfs_test.cpp @@ -33,6 +33,10 @@ TEST(LlvmLibcSysStatvfsTest, StatvfsInvalidPath) { constexpr const char *FILENAME = "statvfs.testdir"; auto TEST_DIR = libc_make_test_file_path(FILENAME); + // Always delete the folder so that we start in a consistent state. + LIBC_NAMESPACE::rmdir(TEST_DIR); + LIBC_NAMESPACE::libc_errno = 0; // Reset errno + ASSERT_THAT(LIBC_NAMESPACE::mkdirat(AT_FDCWD, TEST_DIR, S_IRWXU), Succeeds(0)); diff --git a/libc/utils/gpu/server/llvmlibc_rpc_server.h b/libc/utils/gpu/server/llvmlibc_rpc_server.h index b0cf2f916b38568e5e35a6363aedf3cf23ed80f8..98df882afa21cf655e333ec208d01ebcf9db44d8 100644 --- a/libc/utils/gpu/server/llvmlibc_rpc_server.h +++ b/libc/utils/gpu/server/llvmlibc_rpc_server.h @@ -79,7 +79,7 @@ rpc_status_t rpc_handle_server(rpc_device_t rpc_device); /// Register a callback to handle an opcode from the RPC client. The associated /// data must remain accessible as long as the user intends to handle the server /// with this callback. -rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint16_t opcode, +rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint32_t opcode, rpc_opcode_callback_ty callback, void *data); /// Obtain a pointer to a local client buffer that can be copied directly to the diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 11b6d0e27ab9481d23f4cbd65fdadd145b459ccd..972601aaf1d5e0fb6599df11b518b81d19c522d7 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -215,8 +215,8 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) { template rpc_status_t handle_server_impl( rpc::Server &server, - const std::unordered_map &callbacks, - const std::unordered_map &callback_data, + const std::unordered_map &callbacks, + const std::unordered_map &callback_data, uint32_t &index) { auto port = server.try_open(lane_size, index); if (!port) @@ -477,8 +477,8 @@ struct Device { void *buffer; rpc::Server server; rpc::Client client; - std::unordered_map callbacks; - std::unordered_map callback_data; + std::unordered_map callbacks; + std::unordered_map callback_data; }; rpc_status_t rpc_server_init(rpc_device_t *rpc_device, uint64_t num_ports, @@ -528,7 +528,7 @@ rpc_status_t rpc_handle_server(rpc_device_t rpc_device) { } } -rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint16_t opcode, +rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint32_t opcode, rpc_opcode_callback_ty callback, void *data) { if (!rpc_device.handle) diff --git a/libclc/clc/include/clc/geometric/clc_dot.h b/libclc/clc/include/clc/geometric/clc_dot.h index e0e47ab2093efdb367df27ae27c0f0293ab70ab5..a7fa4e11d6588f1da95eead2d098e57c7da47a04 100644 --- a/libclc/clc/include/clc/geometric/clc_dot.h +++ b/libclc/clc/include/clc/geometric/clc_dot.h @@ -1,2 +1,7 @@ +#ifndef __CLC_GEOMETRIC_CLC_DOT_H__ +#define __CLC_GEOMETRIC_CLC_DOT_H__ + #define __CLC_BODY #include + +#endif // __CLC_GEOMETRIC_CLC_DOT_H__ diff --git a/libclc/clc/include/clc/shared/clc_clamp.h b/libclc/clc/include/clc/shared/clc_clamp.h index 5c044c9a1a510db40849b0a40bb30d999edc040d..a84184c1750a586d3c8a00e4a67aa375e5df6717 100644 --- a/libclc/clc/include/clc/shared/clc_clamp.h +++ b/libclc/clc/include/clc/shared/clc_clamp.h @@ -1,3 +1,6 @@ +#ifndef __CLC_SHARED_CLC_CLAMP_H__ +#define __CLC_SHARED_CLC_CLAMP_H__ + #if defined(CLC_CLSPV) || defined(CLC_SPIRV) // clspv and spir-v targets provide their own OpenCL-compatible clamp #define __clc_clamp clamp @@ -13,3 +16,5 @@ #include #endif + +#endif // __CLC_SHARED_CLC_CLAMP_H__ diff --git a/libclc/clc/include/clc/shared/clc_max.h b/libclc/clc/include/clc/shared/clc_max.h index 2825640f6c2913be1f09709227e13c9a602f0a05..388f001a277823d4eb3fb815e74260c163d50b7a 100644 --- a/libclc/clc/include/clc/shared/clc_max.h +++ b/libclc/clc/include/clc/shared/clc_max.h @@ -1,3 +1,6 @@ +#ifndef __CLC_SHARED_CLC_MAX_H__ +#define __CLC_SHARED_CLC_MAX_H__ + #if defined(CLC_CLSPV) || defined(CLC_SPIRV) // clspv and spir-v targets provide their own OpenCL-compatible max #define __clc_max max @@ -10,3 +13,5 @@ #include #endif + +#endif // __CLC_SHARED_CLC_MAX_H__ diff --git a/libclc/clc/include/clc/shared/clc_min.h b/libclc/clc/include/clc/shared/clc_min.h index 0b7ee140b8f452f652ec53ac9a1cc548d26abcd7..c8d920e1b4eb88388efdfb9d2760e19abc8bb849 100644 --- a/libclc/clc/include/clc/shared/clc_min.h +++ b/libclc/clc/include/clc/shared/clc_min.h @@ -1,3 +1,6 @@ +#ifndef __CLC_SHARED_CLC_MIN_H__ +#define __CLC_SHARED_CLC_MIN_H__ + #if defined(CLC_CLSPV) || defined(CLC_SPIRV) // clspv and spir-v targets provide their own OpenCL-compatible min #define __clc_min min @@ -10,3 +13,5 @@ #include #endif + +#endif // __CLC_SHARED_CLC_MIN_H__ diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake index ee7c8500c8359fb3593eaba1d8b979ec63d3fb3b..b520626c6ffd1366bdb844b8ade294937355d0e3 100644 --- a/libclc/cmake/modules/AddLibclc.cmake +++ b/libclc/cmake/modules/AddLibclc.cmake @@ -355,11 +355,14 @@ function(add_libclc_builtin_set) 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_target( ${alias_suffix} ALL + add_custom_command( + OUTPUT ${alias_suffix} COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix} DEPENDS prepare-${obj_suffix} ) - set_target_properties( "${alias_suffix}" PROPERTIES FOLDER "libclc/Device IR/Aliases" ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) + 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/generic/lib/gen_convert.py b/libclc/generic/lib/gen_convert.py index 41bd8cebf88b60b22eb15cfa50129afadef03699..d2f69e602a29dac7c0a6e073b78bdef763168427 100644 --- a/libclc/generic/lib/gen_convert.py +++ b/libclc/generic/lib/gen_convert.py @@ -241,41 +241,21 @@ print( def generate_default_conversion(src, dst, mode): close_conditional = conditional_guard(src, dst) - # scalar conversions - print( - """_CLC_DEF _CLC_OVERLOAD -{DST} convert_{DST}{M}({SRC} x) -{{ - return ({DST})x; + for size in vector_sizes: + if not size: + print( + f"""_CLC_DEF _CLC_OVERLOAD {dst} convert_{dst}{mode}({src} x) {{ + return ({dst})x; }} -""".format( - SRC=src, DST=dst, M=mode - ) - ) - - # vector conversions, done through decomposition to components - for size, half_size in half_sizes: - print( - """_CLC_DEF _CLC_OVERLOAD -{DST}{N} convert_{DST}{N}{M}({SRC}{N} x) -{{ - return ({DST}{N})(convert_{DST}{H}(x.lo), convert_{DST}{H}(x.hi)); +""" + ) + else: + print( + f"""_CLC_DEF _CLC_OVERLOAD {dst}{size} convert_{dst}{size}{mode}({src}{size} x) {{ + return __builtin_convertvector(x, {dst}{size}); }} -""".format( - SRC=src, DST=dst, N=size, H=half_size, M=mode +""" ) - ) - - # 3-component vector conversions - print( - """_CLC_DEF _CLC_OVERLOAD -{DST}3 convert_{DST}3{M}({SRC}3 x) -{{ - return ({DST}3)(convert_{DST}2(x.s01), convert_{DST}(x.s2)); -}}""".format( - SRC=src, DST=dst, M=mode - ) - ) if close_conditional: print("#endif") diff --git a/libclc/generic/lib/math/clc_remquo.cl b/libclc/generic/lib/math/clc_remquo.cl index e5ff969b4d97a25e0db1782201d7e6c33282f732..8d2e5f9a74bfef06ec27fd9b044c784e9a9b47cb 100644 --- a/libclc/generic/lib/math/clc_remquo.cl +++ b/libclc/generic/lib/math/clc_remquo.cl @@ -25,234 +25,248 @@ #include #include #include - #include + #include "config.h" #include "math.h" -_CLC_DEF _CLC_OVERLOAD float __clc_remquo(float x, float y, __private int *quo) -{ - x = __clc_flush_denormal_if_not_supported(x); - y = __clc_flush_denormal_if_not_supported(y); - int ux = as_int(x); - int ax = ux & EXSIGNBIT_SP32; - float xa = as_float(ax); - int sx = ux ^ ax; - int ex = ax >> EXPSHIFTBITS_SP32; - - int uy = as_int(y); - int ay = uy & EXSIGNBIT_SP32; - float ya = as_float(ay); - int sy = uy ^ ay; - int ey = ay >> EXPSHIFTBITS_SP32; - - float xr = as_float(0x3f800000 | (ax & 0x007fffff)); - float yr = as_float(0x3f800000 | (ay & 0x007fffff)); - int c; - int k = ex - ey; - - uint q = 0; - - while (k > 0) { - c = xr >= yr; - q = (q << 1) | c; - xr -= c ? yr : 0.0f; - xr += xr; - --k; - } - - c = xr > yr; +_CLC_DEF _CLC_OVERLOAD float __clc_remquo(float x, float y, + __private int *quo) { + x = __clc_flush_denormal_if_not_supported(x); + y = __clc_flush_denormal_if_not_supported(y); + int ux = as_int(x); + int ax = ux & EXSIGNBIT_SP32; + float xa = as_float(ax); + int sx = ux ^ ax; + int ex = ax >> EXPSHIFTBITS_SP32; + + int uy = as_int(y); + int ay = uy & EXSIGNBIT_SP32; + float ya = as_float(ay); + int sy = uy ^ ay; + int ey = ay >> EXPSHIFTBITS_SP32; + + float xr = as_float(0x3f800000 | (ax & 0x007fffff)); + float yr = as_float(0x3f800000 | (ay & 0x007fffff)); + int c; + int k = ex - ey; + + uint q = 0; + + while (k > 0) { + c = xr >= yr; q = (q << 1) | c; xr -= c ? yr : 0.0f; + xr += xr; + --k; + } - int lt = ex < ey; + c = xr > yr; + q = (q << 1) | c; + xr -= c ? yr : 0.0f; - q = lt ? 0 : q; - xr = lt ? xa : xr; - yr = lt ? ya : yr; + int lt = ex < ey; - c = (yr < 2.0f * xr) | ((yr == 2.0f * xr) & ((q & 0x1) == 0x1)); - xr -= c ? yr : 0.0f; - q += c; + q = lt ? 0 : q; + xr = lt ? xa : xr; + yr = lt ? ya : yr; - float s = as_float(ey << EXPSHIFTBITS_SP32); - xr *= lt ? 1.0f : s; + c = (yr < 2.0f * xr) | ((yr == 2.0f * xr) & ((q & 0x1) == 0x1)); + xr -= c ? yr : 0.0f; + q += c; - int qsgn = sx == sy ? 1 : -1; - int quot = (q & 0x7f) * qsgn; + float s = as_float(ey << EXPSHIFTBITS_SP32); + xr *= lt ? 1.0f : s; - c = ax == ay; - quot = c ? qsgn : quot; - xr = c ? 0.0f : xr; + int qsgn = sx == sy ? 1 : -1; + int quot = (q & 0x7f) * qsgn; - xr = as_float(sx ^ as_int(xr)); + c = ax == ay; + quot = c ? qsgn : quot; + xr = c ? 0.0f : xr; - c = ax > PINFBITPATT_SP32 | ay > PINFBITPATT_SP32 | ax == PINFBITPATT_SP32 | ay == 0; - quot = c ? 0 : quot; - xr = c ? as_float(QNANBITPATT_SP32) : xr; + xr = as_float(sx ^ as_int(xr)); - *quo = quot; + c = ax > PINFBITPATT_SP32 | ay > PINFBITPATT_SP32 | ax == PINFBITPATT_SP32 | + ay == 0; + quot = c ? 0 : quot; + xr = c ? as_float(QNANBITPATT_SP32) : xr; - return xr; -} -// remquo singature is special, we don't have macro for this -#define __VEC_REMQUO(TYPE, VEC_SIZE, HALF_VEC_SIZE) \ -_CLC_DEF _CLC_OVERLOAD TYPE##VEC_SIZE __clc_remquo(TYPE##VEC_SIZE x, TYPE##VEC_SIZE y, __private int##VEC_SIZE *quo) \ -{ \ - int##HALF_VEC_SIZE lo, hi; \ - TYPE##VEC_SIZE ret; \ - ret.lo = __clc_remquo(x.lo, y.lo, &lo); \ - ret.hi = __clc_remquo(x.hi, y.hi, &hi); \ - (*quo).lo = lo; \ - (*quo).hi = hi; \ - return ret; \ + *quo = quot; + + return xr; } -__VEC_REMQUO(float, 2,) -__VEC_REMQUO(float, 3, 2) +// remquo signature is special, we don't have macro for this +#define __VEC_REMQUO(TYPE, VEC_SIZE, HALF_VEC_SIZE) \ + _CLC_DEF _CLC_OVERLOAD TYPE##VEC_SIZE __clc_remquo( \ + TYPE##VEC_SIZE x, TYPE##VEC_SIZE y, __private int##VEC_SIZE *quo) { \ + int##HALF_VEC_SIZE lo, hi; \ + TYPE##VEC_SIZE ret; \ + ret.lo = __clc_remquo(x.lo, y.lo, &lo); \ + ret.hi = __clc_remquo(x.hi, y.hi, &hi); \ + (*quo).lo = lo; \ + (*quo).hi = hi; \ + return ret; \ + } + +#define __VEC3_REMQUO(TYPE) \ + _CLC_DEF _CLC_OVERLOAD TYPE##3 __clc_remquo(TYPE##3 x, TYPE##3 y, \ + __private int##3 * quo) { \ + int2 lo; \ + int hi; \ + TYPE##3 ret; \ + ret.s01 = __clc_remquo(x.s01, y.s01, &lo); \ + ret.s2 = __clc_remquo(x.s2, y.s2, &hi); \ + (*quo).s01 = lo; \ + (*quo).s2 = hi; \ + return ret; \ + } +__VEC_REMQUO(float, 2, ) +__VEC3_REMQUO(float) __VEC_REMQUO(float, 4, 2) __VEC_REMQUO(float, 8, 4) __VEC_REMQUO(float, 16, 8) #ifdef cl_khr_fp64 -_CLC_DEF _CLC_OVERLOAD double __clc_remquo(double x, double y, __private int *pquo) -{ - ulong ux = as_ulong(x); - ulong ax = ux & ~SIGNBIT_DP64; - ulong xsgn = ux ^ ax; - double dx = as_double(ax); - int xexp = convert_int(ax >> EXPSHIFTBITS_DP64); - int xexp1 = 11 - (int) clz(ax & MANTBITS_DP64); - xexp1 = xexp < 1 ? xexp1 : xexp; - - ulong uy = as_ulong(y); - ulong ay = uy & ~SIGNBIT_DP64; - double dy = as_double(ay); - int yexp = convert_int(ay >> EXPSHIFTBITS_DP64); - int yexp1 = 11 - (int) clz(ay & MANTBITS_DP64); - yexp1 = yexp < 1 ? yexp1 : yexp; - - int qsgn = ((ux ^ uy) & SIGNBIT_DP64) == 0UL ? 1 : -1; - - // First assume |x| > |y| - - // Set ntimes to the number of times we need to do a - // partial remainder. If the exponent of x is an exact multiple - // of 53 larger than the exponent of y, and the mantissa of x is - // less than the mantissa of y, ntimes will be one too large - // but it doesn't matter - it just means that we'll go round - // the loop below one extra time. - int ntimes = __clc_max(0, (xexp1 - yexp1) / 53); - double w = ldexp(dy, ntimes * 53); - w = ntimes == 0 ? dy : w; - double scale = ntimes == 0 ? 1.0 : 0x1.0p-53; - - // Each time round the loop we compute a partial remainder. - // This is done by subtracting a large multiple of w - // from x each time, where w is a scaled up version of y. - // The subtraction must be performed exactly in quad - // precision, though the result at each stage can - // fit exactly in a double precision number. - int i; - double t, v, p, pp; - - for (i = 0; i < ntimes; i++) { - // Compute integral multiplier - t = __clc_trunc(dx / w); - - // Compute w * t in quad precision - p = w * t; - pp = fma(w, t, -p); - - // Subtract w * t from dx - v = dx - p; - dx = v + (((dx - v) - p) - pp); - - // If t was one too large, dx will be negative. Add back one w. - dx += dx < 0.0 ? w : 0.0; - - // Scale w down by 2^(-53) for the next iteration - w *= scale; - } - - // One more time - // Variable todd says whether the integer t is odd or not - t = __clc_floor(dx / w); - long lt = (long)t; - int todd = lt & 1; - +_CLC_DEF _CLC_OVERLOAD double __clc_remquo(double x, double y, + __private int *pquo) { + ulong ux = as_ulong(x); + ulong ax = ux & ~SIGNBIT_DP64; + ulong xsgn = ux ^ ax; + double dx = as_double(ax); + int xexp = convert_int(ax >> EXPSHIFTBITS_DP64); + int xexp1 = 11 - (int)clz(ax & MANTBITS_DP64); + xexp1 = xexp < 1 ? xexp1 : xexp; + + ulong uy = as_ulong(y); + ulong ay = uy & ~SIGNBIT_DP64; + double dy = as_double(ay); + int yexp = convert_int(ay >> EXPSHIFTBITS_DP64); + int yexp1 = 11 - (int)clz(ay & MANTBITS_DP64); + yexp1 = yexp < 1 ? yexp1 : yexp; + + int qsgn = ((ux ^ uy) & SIGNBIT_DP64) == 0UL ? 1 : -1; + + // First assume |x| > |y| + + // Set ntimes to the number of times we need to do a + // partial remainder. If the exponent of x is an exact multiple + // of 53 larger than the exponent of y, and the mantissa of x is + // less than the mantissa of y, ntimes will be one too large + // but it doesn't matter - it just means that we'll go round + // the loop below one extra time. + int ntimes = __clc_max(0, (xexp1 - yexp1) / 53); + double w = ldexp(dy, ntimes * 53); + w = ntimes == 0 ? dy : w; + double scale = ntimes == 0 ? 1.0 : 0x1.0p-53; + + // Each time round the loop we compute a partial remainder. + // This is done by subtracting a large multiple of w + // from x each time, where w is a scaled up version of y. + // The subtraction must be performed exactly in quad + // precision, though the result at each stage can + // fit exactly in a double precision number. + int i; + double t, v, p, pp; + + for (i = 0; i < ntimes; i++) { + // Compute integral multiplier + t = __clc_trunc(dx / w); + + // Compute w * t in quad precision p = w * t; pp = fma(w, t, -p); + + // Subtract w * t from dx v = dx - p; dx = v + (((dx - v) - p) - pp); - i = dx < 0.0; - todd ^= i; - dx += i ? w : 0.0; - - lt -= i; - - // At this point, dx lies in the range [0,dy) - - // For the remainder function, we need to adjust dx - // so that it lies in the range (-y/2, y/2] by carefully - // subtracting w (== dy == y) if necessary. The rigmarole - // with todd is to get the correct sign of the result - // when x/y lies exactly half way between two integers, - // when we need to choose the even integer. - - int al = (2.0*dx > w) | (todd & (2.0*dx == w)); - double dxl = dx - (al ? w : 0.0); - - int ag = (dx > 0.5*w) | (todd & (dx == 0.5*w)); - double dxg = dx - (ag ? w : 0.0); - - dx = dy < 0x1.0p+1022 ? dxl : dxg; - lt += dy < 0x1.0p+1022 ? al : ag; - int quo = ((int)lt & 0x7f) * qsgn; - - double ret = as_double(xsgn ^ as_ulong(dx)); - dx = as_double(ax); - - // Now handle |x| == |y| - int c = dx == dy; - t = as_double(xsgn); - quo = c ? qsgn : quo; - ret = c ? t : ret; - - // Next, handle |x| < |y| - c = dx < dy; - quo = c ? 0 : quo; - ret = c ? x : ret; - - c &= (yexp < 1023 & 2.0*dx > dy) | (dx > 0.5*dy); - quo = c ? qsgn : quo; - // we could use a conversion here instead since qsgn = +-1 - p = qsgn == 1 ? -1.0 : 1.0; - t = fma(y, p, x); - ret = c ? t : ret; - - // We don't need anything special for |x| == 0 - - // |y| is 0 - c = dy == 0.0; - quo = c ? 0 : quo; - ret = c ? as_double(QNANBITPATT_DP64) : ret; - - // y is +-Inf, NaN - c = yexp > BIASEDEMAX_DP64; - quo = c ? 0 : quo; - t = y == y ? x : y; - ret = c ? t : ret; - - // x is +=Inf, NaN - c = xexp > BIASEDEMAX_DP64; - quo = c ? 0 : quo; - ret = c ? as_double(QNANBITPATT_DP64) : ret; - - *pquo = quo; - return ret; + + // If t was one too large, dx will be negative. Add back one w. + dx += dx < 0.0 ? w : 0.0; + + // Scale w down by 2^(-53) for the next iteration + w *= scale; + } + + // One more time + // Variable todd says whether the integer t is odd or not + t = __clc_floor(dx / w); + long lt = (long)t; + int todd = lt & 1; + + p = w * t; + pp = fma(w, t, -p); + v = dx - p; + dx = v + (((dx - v) - p) - pp); + i = dx < 0.0; + todd ^= i; + dx += i ? w : 0.0; + + lt -= i; + + // At this point, dx lies in the range [0,dy) + + // For the remainder function, we need to adjust dx + // so that it lies in the range (-y/2, y/2] by carefully + // subtracting w (== dy == y) if necessary. The rigmarole + // with todd is to get the correct sign of the result + // when x/y lies exactly half way between two integers, + // when we need to choose the even integer. + + int al = (2.0 * dx > w) | (todd & (2.0 * dx == w)); + double dxl = dx - (al ? w : 0.0); + + int ag = (dx > 0.5 * w) | (todd & (dx == 0.5 * w)); + double dxg = dx - (ag ? w : 0.0); + + dx = dy < 0x1.0p+1022 ? dxl : dxg; + lt += dy < 0x1.0p+1022 ? al : ag; + int quo = ((int)lt & 0x7f) * qsgn; + + double ret = as_double(xsgn ^ as_ulong(dx)); + dx = as_double(ax); + + // Now handle |x| == |y| + int c = dx == dy; + t = as_double(xsgn); + quo = c ? qsgn : quo; + ret = c ? t : ret; + + // Next, handle |x| < |y| + c = dx < dy; + quo = c ? 0 : quo; + ret = c ? x : ret; + + c &= (yexp<1023 & 2.0 * dx> dy) | (dx > 0.5 * dy); + quo = c ? qsgn : quo; + // we could use a conversion here instead since qsgn = +-1 + p = qsgn == 1 ? -1.0 : 1.0; + t = fma(y, p, x); + ret = c ? t : ret; + + // We don't need anything special for |x| == 0 + + // |y| is 0 + c = dy == 0.0; + quo = c ? 0 : quo; + ret = c ? as_double(QNANBITPATT_DP64) : ret; + + // y is +-Inf, NaN + c = yexp > BIASEDEMAX_DP64; + quo = c ? 0 : quo; + t = y == y ? x : y; + ret = c ? t : ret; + + // x is +=Inf, NaN + c = xexp > BIASEDEMAX_DP64; + quo = c ? 0 : quo; + ret = c ? as_double(QNANBITPATT_DP64) : ret; + + *pquo = quo; + return ret; } -__VEC_REMQUO(double, 2,) -__VEC_REMQUO(double, 3, 2) +__VEC_REMQUO(double, 2, ) +__VEC3_REMQUO(double) __VEC_REMQUO(double, 4, 2) __VEC_REMQUO(double, 8, 4) __VEC_REMQUO(double, 16, 8) @@ -263,10 +277,10 @@ __VEC_REMQUO(double, 16, 8) #pragma OPENCL EXTENSION cl_khr_fp16 : enable _CLC_OVERLOAD _CLC_DEF half __clc_remquo(half x, half y, __private int *pquo) { - return (half)__clc_remquo((float)x, (float)y, pquo); + return (half)__clc_remquo((float)x, (float)y, pquo); } -__VEC_REMQUO(half, 2,) -__VEC_REMQUO(half, 3, 2) +__VEC_REMQUO(half, 2, ) +__VEC3_REMQUO(half) __VEC_REMQUO(half, 4, 2) __VEC_REMQUO(half, 8, 4) __VEC_REMQUO(half, 16, 8) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index d699135774ee0b6711c1b57c44ed7625ca5d1532..abe12c2805a7cf870648607c982362196d20953b 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -47,6 +47,10 @@ include(HandleCompilerRT) # Basic options --------------------------------------------------------------- option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON) option(LIBCXX_ENABLE_STATIC "Build libc++ as a static library." ON) +option(LIBCXX_ENABLE_EXCEPTIONS "Enable exceptions in the built library." ON) +option(LIBCXX_ENABLE_RTTI + "Use runtime type information. + This option may only be set to OFF when LIBCXX_ENABLE_EXCEPTIONS=OFF." ON) option(LIBCXX_ENABLE_FILESYSTEM "Whether to include support for parts of the library that rely on a filesystem being available on the platform. This includes things like most parts of and @@ -97,6 +101,10 @@ option(LIBCXX_ENABLE_WIDE_CHARACTERS support the C functionality for wide characters. When wide characters are not supported, several parts of the library will be disabled, notably the wide character specializations of std::basic_string." ON) +option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON) +option(LIBCXX_ENABLE_MONOTONIC_CLOCK + "Build libc++ with support for a monotonic clock. + This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON) # To use time zone support in libc++ the platform needs to have the IANA # database installed. Libc++ will fail to build if this is enabled on a @@ -284,14 +292,6 @@ if (LIBCXX_BUILD_32_BITS) endif() # Feature options ------------------------------------------------------------- -option(LIBCXX_ENABLE_EXCEPTIONS "Use exceptions." ON) -option(LIBCXX_ENABLE_RTTI - "Use runtime type information. - This option may only be set to OFF when LIBCXX_ENABLE_EXCEPTIONS=OFF." ON) -option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON) -option(LIBCXX_ENABLE_MONOTONIC_CLOCK - "Build libc++ with support for a monotonic clock. - This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON) option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF) option(LIBCXX_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF) option(LIBCXX_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of win32 thread API" OFF) diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv index aa59cabf24f781f8dc01f6be90913963772ae3b5..a589207085d36fad368776267b36b3b3360cb44f 100644 --- a/libcxx/docs/Status/Cxx17Papers.csv +++ b/libcxx/docs/Status/Cxx17Papers.csv @@ -71,7 +71,7 @@ "`P0394R4 `__","Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling","2016-06 (Oulu)","|Complete|","17","" "","","","","","" "`P0003R5 `__","Removing Deprecated Exception Specifications from C++17","2016-11 (Issaquah)","|Complete|","5","" -"`P0067R5 `__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","``std::(to|from)_chars`` for integrals has been available since version 7. ``std::to_chars`` for ``float`` and ``double`` since version 14 ``std::to_chars`` for ``long double`` uses the implementation for ``double``. ``std::from_chars`` for ``float`` and ``double`` since version 20." +"`P0067R5 `__","Elementary string conversions, revision 5","2016-11 (Issaquah)","|Partial|","","For integer types, ``std::(to|from)_chars`` has been available since v7; for ``float`` and ``double``, ``std::to_chars`` since v14 and ``std::from_chars`` since v20. Support is complete except for ``long double``." "`P0403R1 `__","Literal suffixes for ``basic_string_view``\ ","2016-11 (Issaquah)","|Complete|","4","" "`P0414R2 `__","Merging shared_ptr changes from Library Fundamentals to C++17","2016-11 (Issaquah)","|Complete|","11","" "`P0418R2 `__","Fail or succeed: there is no atomic lattice","2016-11 (Issaquah)","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index dd774b25a81eda92d46c370e6dd504df89b938a7..0ae031e5365aefed292b1dbf6b7ad649f8e0334c 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -205,7 +205,6 @@ set(files __assert __atomic/aliases.h __atomic/atomic.h - __atomic/atomic_base.h __atomic/atomic_flag.h __atomic/atomic_init.h __atomic/atomic_lock_free.h @@ -503,6 +502,7 @@ set(files __locale_dir/locale_base_api/openbsd.h __locale_dir/locale_base_api/win32.h __locale_dir/locale_guard.h + __locale_dir/pad_and_output.h __locale_dir/support/apple.h __locale_dir/support/bsd_like.h __locale_dir/support/freebsd.h @@ -557,6 +557,7 @@ set(files __memory/ranges_construct_at.h __memory/ranges_uninitialized_algorithms.h __memory/raw_storage_iterator.h + __memory/shared_count.h __memory/shared_ptr.h __memory/swap_allocator.h __memory/temp_value.h @@ -595,6 +596,7 @@ set(files __numeric/transform_reduce.h __ostream/basic_ostream.h __ostream/print.h + __ostream/put_character_sequence.h __pstl/backend.h __pstl/backend_fwd.h __pstl/backends/default.h @@ -715,6 +717,7 @@ set(files __system_error/error_code.h __system_error/error_condition.h __system_error/system_error.h + __system_error/throw_system_error.h __thread/formatter.h __thread/id.h __thread/jthread.h diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 7ae47514d6d27fc6f73b0a48d6ae05234cfa24ed..4f30b2050abbafcde0edc65759d5c57e3b05fe2b 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -11,7 +11,6 @@ #include <__algorithm/copy_move_common.h> #include <__algorithm/for_each_segment.h> -#include <__algorithm/iterator_operations.h> #include <__algorithm/min.h> #include <__config> #include <__iterator/iterator_traits.h> @@ -30,10 +29,9 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template +template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); -template struct __copy_impl { template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> @@ -58,7 +56,7 @@ struct __copy_impl { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void operator()(typename _Traits::__local_iterator __lfirst, typename _Traits::__local_iterator __llast) { - __result_ = std::__copy<_AlgPolicy>(__lfirst, __llast, std::move(__result_)).second; + __result_ = std::__copy(__lfirst, __llast, std::move(__result_)).second; } }; @@ -87,7 +85,7 @@ struct __copy_impl { while (true) { auto __local_last = _Traits::__end(__segment_iterator); auto __size = std::min<_DiffT>(__local_last - __local_first, __last - __first); - auto __iters = std::__copy<_AlgPolicy>(__first, __first + __size, __local_first); + auto __iters = std::__copy(__first, __first + __size, __local_first); __first = std::move(__iters.first); if (__first == __last) @@ -105,17 +103,16 @@ struct __copy_impl { } }; -template +template pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __copy(_InIter __first, _Sent __last, _OutIter __result) { - return std::__copy_move_unwrap_iters<__copy_impl<_AlgPolicy> >( - std::move(__first), std::move(__last), std::move(__result)); + return std::__copy_move_unwrap_iters<__copy_impl>(std::move(__first), std::move(__last), std::move(__result)); } template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return std::__copy<_ClassicAlgPolicy>(__first, __last, __result).second; + return std::__copy(__first, __last, __result).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/copy_move_common.h b/libcxx/include/__algorithm/copy_move_common.h index d76bf4903aaa9b489d285656eca5dbb157d9e298..7471012c01d969134d9f39c4a150ca7bc32767ed 100644 --- a/libcxx/include/__algorithm/copy_move_common.h +++ b/libcxx/include/__algorithm/copy_move_common.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H #define _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H -#include <__algorithm/iterator_operations.h> #include <__algorithm/unwrap_iter.h> #include <__algorithm/unwrap_range.h> #include <__config> diff --git a/libcxx/include/__algorithm/find_end.h b/libcxx/include/__algorithm/find_end.h index 08d1a295f8e5c04a20a5d8809ee036f7883f57f9..fc876d872676110ef942e3d44c0fecd5597de807 100644 --- a/libcxx/include/__algorithm/find_end.h +++ b/libcxx/include/__algorithm/find_end.h @@ -12,13 +12,10 @@ #include <__algorithm/comp.h> #include <__algorithm/iterator_operations.h> -#include <__algorithm/search.h> #include <__config> #include <__functional/identity.h> -#include <__iterator/advance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> -#include <__iterator/reverse_iterator.h> #include <__type_traits/invoke.h> #include <__utility/pair.h> diff --git a/libcxx/include/__algorithm/ranges_copy.h b/libcxx/include/__algorithm/ranges_copy.h index 05b61c0d5d4abb73dc04974909a1b4564283a7ff..a69af9b2bffc3182d8244eaebc0f20ae1250f775 100644 --- a/libcxx/include/__algorithm/ranges_copy.h +++ b/libcxx/include/__algorithm/ranges_copy.h @@ -11,7 +11,6 @@ #include <__algorithm/copy.h> #include <__algorithm/in_out_result.h> -#include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> #include <__iterator/concepts.h> @@ -42,7 +41,7 @@ struct __copy { requires indirectly_copyable<_InIter, _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr copy_result<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { - auto __ret = std::__copy<_RangeAlgPolicy>(std::move(__first), std::move(__last), std::move(__result)); + auto __ret = std::__copy(std::move(__first), std::move(__last), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -50,7 +49,7 @@ struct __copy { requires indirectly_copyable, _OutIter> _LIBCPP_HIDE_FROM_ABI constexpr copy_result, _OutIter> operator()(_Range&& __r, _OutIter __result) const { - auto __ret = std::__copy<_RangeAlgPolicy>(ranges::begin(__r), ranges::end(__r), std::move(__result)); + auto __ret = std::__copy(ranges::begin(__r), ranges::end(__r), std::move(__result)); return {std::move(__ret.first), std::move(__ret.second)}; } }; diff --git a/libcxx/include/__algorithm/ranges_copy_n.h b/libcxx/include/__algorithm/ranges_copy_n.h index 79ce1580490d432057bd766424940d643a1e06ed..1fbc61674e2ddf52e24288a717b9f7cde585c89a 100644 --- a/libcxx/include/__algorithm/ranges_copy_n.h +++ b/libcxx/include/__algorithm/ranges_copy_n.h @@ -54,7 +54,7 @@ struct __copy_n { template _LIBCPP_HIDE_FROM_ABI constexpr static copy_n_result<_InIter, _OutIter> __go(_InIter __first, _DiffType __n, _OutIter __result) { - auto __ret = std::__copy<_RangeAlgPolicy>(__first, __first + __n, __result); + auto __ret = std::__copy(__first, __first + __n, __result); return {__ret.first, __ret.second}; } diff --git a/libcxx/include/__algorithm/ranges_set_difference.h b/libcxx/include/__algorithm/ranges_set_difference.h index aa36e358ef6f98ed90eb5e595839ebbe0c6cefb9..1c83c7bdd5a33e748364c5c35a38a783f3b508ae 100644 --- a/libcxx/include/__algorithm/ranges_set_difference.h +++ b/libcxx/include/__algorithm/ranges_set_difference.h @@ -10,7 +10,6 @@ #define _LIBCPP___ALGORITHM_RANGES_SET_DIFFERENCE_H #include <__algorithm/in_out_result.h> -#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/set_difference.h> #include <__config> @@ -61,7 +60,7 @@ struct __set_difference { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_difference<_RangeAlgPolicy>( + auto __ret = std::__set_difference( __first1, __last1, __first2, __last2, __result, ranges::__make_projected_comp(__comp, __proj1, __proj2)); return {std::move(__ret.first), std::move(__ret.second)}; } @@ -80,7 +79,7 @@ struct __set_difference { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_difference<_RangeAlgPolicy>( + auto __ret = std::__set_difference( ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), diff --git a/libcxx/include/__algorithm/ranges_set_symmetric_difference.h b/libcxx/include/__algorithm/ranges_set_symmetric_difference.h index e3b73c3eb1cf24767a88ef65e645aecf63af4736..c0a814043192c63a4d034400e30d75ca970564a7 100644 --- a/libcxx/include/__algorithm/ranges_set_symmetric_difference.h +++ b/libcxx/include/__algorithm/ranges_set_symmetric_difference.h @@ -10,7 +10,6 @@ #define _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H #include <__algorithm/in_in_out_result.h> -#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/set_symmetric_difference.h> #include <__config> @@ -59,7 +58,7 @@ struct __set_symmetric_difference { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( + auto __ret = std::__set_symmetric_difference( std::move(__first1), std::move(__last1), std::move(__first2), @@ -85,7 +84,7 @@ struct __set_symmetric_difference { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>( + auto __ret = std::__set_symmetric_difference( ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), diff --git a/libcxx/include/__algorithm/ranges_set_union.h b/libcxx/include/__algorithm/ranges_set_union.h index f2e3ddb89d7b35ab58adf8dfa7e9bffd2b3a7587..039ffb5932f3af016bd4cc9c12e599c59fd0029f 100644 --- a/libcxx/include/__algorithm/ranges_set_union.h +++ b/libcxx/include/__algorithm/ranges_set_union.h @@ -10,7 +10,6 @@ #define _LIBCPP___ALGORITHM_RANGES_SET_UNION_H #include <__algorithm/in_in_out_result.h> -#include <__algorithm/iterator_operations.h> #include <__algorithm/make_projected.h> #include <__algorithm/set_union.h> #include <__config> @@ -62,7 +61,7 @@ struct __set_union { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_union<_RangeAlgPolicy>( + auto __ret = std::__set_union( std::move(__first1), std::move(__last1), std::move(__first2), @@ -86,7 +85,7 @@ struct __set_union { _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { - auto __ret = std::__set_union<_RangeAlgPolicy>( + auto __ret = std::__set_union( ranges::begin(__range1), ranges::end(__range1), ranges::begin(__range2), diff --git a/libcxx/include/__algorithm/set_difference.h b/libcxx/include/__algorithm/set_difference.h index 6230b831aeda217ed57ffeb739fa4f6fc7577d85..0cd1bc45d64f761bac4cc456c5cc9a05fe8175ab 100644 --- a/libcxx/include/__algorithm/set_difference.h +++ b/libcxx/include/__algorithm/set_difference.h @@ -12,7 +12,6 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> -#include <__algorithm/iterator_operations.h> #include <__config> #include <__functional/identity.h> #include <__iterator/iterator_traits.h> @@ -29,7 +28,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__remove_cvref_t<_InIter1>, __remove_cvref_t<_OutIter> > __set_difference( _InIter1&& __first1, _Sent1&& __last1, _InIter2&& __first2, _Sent2&& __last2, _OutIter&& __result, _Comp&& __comp) { @@ -45,7 +44,7 @@ __set_difference( ++__first2; } } - return std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); + return std::__copy(std::move(__first1), std::move(__last1), std::move(__result)); } template @@ -56,8 +55,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_d _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { - return std::__set_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( - __first1, __last1, __first2, __last2, __result, __comp) + return std::__set_difference<__comp_ref_type<_Compare> >(__first1, __last1, __first2, __last2, __result, __comp) .second; } @@ -68,7 +66,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_d _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result) { - return std::__set_difference<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __result, __less<>()).second; + return std::__set_difference(__first1, __last1, __first2, __last2, __result, __less<>()).second; } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/set_symmetric_difference.h b/libcxx/include/__algorithm/set_symmetric_difference.h index db36665a61365cdfe2892f6d19f5b97a544fe8e1..91ea4067c0d0f770ee395e1dfbc797ed62346ea1 100644 --- a/libcxx/include/__algorithm/set_symmetric_difference.h +++ b/libcxx/include/__algorithm/set_symmetric_difference.h @@ -12,7 +12,6 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> -#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -39,13 +38,13 @@ struct __set_symmetric_difference_result { : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} }; -template +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> __set_symmetric_difference( _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { while (__first1 != __last1) { if (__first2 == __last2) { - auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); + auto __ret1 = std::__copy(std::move(__first1), std::move(__last1), std::move(__result)); return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>( std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); } @@ -63,7 +62,7 @@ __set_symmetric_difference( ++__first2; } } - auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result)); + auto __ret2 = std::__copy(std::move(__first2), std::move(__last2), std::move(__result)); return __set_symmetric_difference_result<_InIter1, _InIter2, _OutIter>( std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); } @@ -76,7 +75,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_symmetri _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { - return std::__set_symmetric_difference<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + return std::__set_symmetric_difference<__comp_ref_type<_Compare> >( std::move(__first1), std::move(__last1), std::move(__first2), diff --git a/libcxx/include/__algorithm/set_union.h b/libcxx/include/__algorithm/set_union.h index a79c50fd3cf2f080405d0fc4b1e04e3813266d33..393dddce4302a2fedd2011ba4510f6b26c86b85a 100644 --- a/libcxx/include/__algorithm/set_union.h +++ b/libcxx/include/__algorithm/set_union.h @@ -12,7 +12,6 @@ #include <__algorithm/comp.h> #include <__algorithm/comp_ref_type.h> #include <__algorithm/copy.h> -#include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> #include <__utility/move.h> @@ -39,12 +38,12 @@ struct __set_union_result { : __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {} }; -template +template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_union_result<_InIter1, _InIter2, _OutIter> __set_union( _InIter1 __first1, _Sent1 __last1, _InIter2 __first2, _Sent2 __last2, _OutIter __result, _Compare&& __comp) { for (; __first1 != __last1; ++__result) { if (__first2 == __last2) { - auto __ret1 = std::__copy<_AlgPolicy>(std::move(__first1), std::move(__last1), std::move(__result)); + auto __ret1 = std::__copy(std::move(__first1), std::move(__last1), std::move(__result)); return __set_union_result<_InIter1, _InIter2, _OutIter>( std::move(__ret1.first), std::move(__first2), std::move((__ret1.second))); } @@ -59,7 +58,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __set_union_result<_InIter1, ++__first1; } } - auto __ret2 = std::__copy<_AlgPolicy>(std::move(__first2), std::move(__last2), std::move(__result)); + auto __ret2 = std::__copy(std::move(__first2), std::move(__last2), std::move(__result)); return __set_union_result<_InIter1, _InIter2, _OutIter>( std::move(__first1), std::move(__ret2.first), std::move((__ret2.second))); } @@ -72,7 +71,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator set_union( _InputIterator2 __last2, _OutputIterator __result, _Compare __comp) { - return std::__set_union<_ClassicAlgPolicy, __comp_ref_type<_Compare> >( + return std::__set_union<__comp_ref_type<_Compare> >( std::move(__first1), std::move(__last1), std::move(__first2), diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 113475cb1f0079fc3d406667895d52b57fd27675..ae0475693f22b485f0f8ddc902e164e792b603eb 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -9,9 +9,10 @@ #ifndef _LIBCPP___ATOMIC_ATOMIC_H #define _LIBCPP___ATOMIC_ATOMIC_H -#include <__atomic/atomic_base.h> +#include <__atomic/atomic_sync.h> #include <__atomic/check_memory_order.h> #include <__atomic/cxx_atomic_impl.h> +#include <__atomic/is_always_lock_free.h> #include <__atomic/memory_order.h> #include <__config> #include <__cstddef/ptrdiff_t.h> @@ -21,6 +22,7 @@ #include <__type_traits/is_floating_point.h> #include <__type_traits/is_function.h> #include <__type_traits/is_integral.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_pointer.h> @@ -34,6 +36,197 @@ _LIBCPP_BEGIN_NAMESPACE_STD +template ::value && !is_same<_Tp, bool>::value> +struct __atomic_base // false +{ + mutable __cxx_atomic_impl<_Tp> __a_; + +#if _LIBCPP_STD_VER >= 17 + static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; +#endif + + _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT { + return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>)); + } + _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT { + return static_cast<__atomic_base const volatile*>(this)->is_lock_free(); + } + _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + std::__cxx_atomic_store(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT + _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { + std::__cxx_atomic_store(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { + return std::__cxx_atomic_load(std::addressof(__a_), __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT + _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { + return std::__cxx_atomic_load(std::addressof(__a_), __m); + } + _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); } + _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); } + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT + _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + _LIBCPP_HIDE_FROM_ABI bool + compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); + } + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const + volatile _NOEXCEPT { + std::__atomic_wait(*this, __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void + wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { + std::__atomic_wait(*this, __v, __m); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { + std::__atomic_notify_one(*this); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { + std::__atomic_notify_all(*this); + } + _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); } +#endif // _LIBCPP_STD_VER >= 20 + +#if _LIBCPP_STD_VER >= 20 + _LIBCPP_HIDE_FROM_ABI constexpr __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} +#else + _LIBCPP_HIDE_FROM_ABI __atomic_base() _NOEXCEPT = default; +#endif + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} + + __atomic_base(const __atomic_base&) = delete; +}; + +// atomic + +template +struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { + using __base = __atomic_base<_Tp, false>; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default; + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} + + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { + return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); + } + _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { + return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); + } + + _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); } + _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } + _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; } + _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; } +}; + +// Here we need _IsIntegral because the default template argument is not enough +// e.g __atomic_base is __atomic_base, which inherits from +// __atomic_base and the caller of the wait function is +// __atomic_base. So specializing __atomic_base<_Tp> does not work +template +struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { + static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) { + return __a.load(__order); + } + + static _LIBCPP_HIDE_FROM_ABI _Tp + __atomic_load(const volatile __atomic_base<_Tp, _IsIntegral>& __this, memory_order __order) { + return __this.load(__order); + } + + static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_Tp>* + __atomic_contention_address(const __atomic_base<_Tp, _IsIntegral>& __a) { + return std::addressof(__a.__a_); + } + + static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_Tp>* + __atomic_contention_address(const volatile __atomic_base<_Tp, _IsIntegral>& __this) { + return std::addressof(__this.__a_); + } +}; + template struct atomic : public __atomic_base<_Tp> { using __base = __atomic_base<_Tp>; @@ -123,6 +316,9 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> { atomic& operator=(const atomic&) volatile = delete; }; +template +struct __atomic_waitable_traits > : __atomic_waitable_traits<__atomic_base<_Tp> > {}; + #if _LIBCPP_STD_VER >= 20 template requires is_floating_point_v<_Tp> diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h deleted file mode 100644 index 93f5c4cff0d1bc511c2a96358ec6e077a89ee0db..0000000000000000000000000000000000000000 --- a/libcxx/include/__atomic/atomic_base.h +++ /dev/null @@ -1,223 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___ATOMIC_ATOMIC_BASE_H -#define _LIBCPP___ATOMIC_ATOMIC_BASE_H - -#include <__atomic/atomic_sync.h> -#include <__atomic/check_memory_order.h> -#include <__atomic/cxx_atomic_impl.h> -#include <__atomic/is_always_lock_free.h> -#include <__atomic/memory_order.h> -#include <__config> -#include <__memory/addressof.h> -#include <__type_traits/is_integral.h> -#include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_same.h> -#include - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template ::value && !is_same<_Tp, bool>::value> -struct __atomic_base // false -{ - mutable __cxx_atomic_impl<_Tp> __a_; - -#if _LIBCPP_STD_VER >= 17 - static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value; -#endif - - _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const volatile _NOEXCEPT { - return __cxx_atomic_is_lock_free(sizeof(__cxx_atomic_impl<_Tp>)); - } - _LIBCPP_HIDE_FROM_ABI bool is_lock_free() const _NOEXCEPT { - return static_cast<__atomic_base const volatile*>(this)->is_lock_free(); - } - _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { - std::__cxx_atomic_store(std::addressof(__a_), __d, __m); - } - _LIBCPP_HIDE_FROM_ABI void store(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT - _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) { - std::__cxx_atomic_store(std::addressof(__a_), __d, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const volatile _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { - return std::__cxx_atomic_load(std::addressof(__a_), __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __m = memory_order_seq_cst) const _NOEXCEPT - _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) { - return std::__cxx_atomic_load(std::addressof(__a_), __m); - } - _LIBCPP_HIDE_FROM_ABI operator _Tp() const volatile _NOEXCEPT { return load(); } - _LIBCPP_HIDE_FROM_ABI operator _Tp() const _NOEXCEPT { return load(); } - _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_exchange(std::addressof(__a_), __d, __m); - } - _LIBCPP_HIDE_FROM_ABI bool - compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { - return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); - } - _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { - return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __s, __f); - } - _LIBCPP_HIDE_FROM_ABI bool - compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) volatile _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { - return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); - } - _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __s, memory_order __f) _NOEXCEPT - _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) { - return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __s, __f); - } - _LIBCPP_HIDE_FROM_ABI bool - compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); - } - _LIBCPP_HIDE_FROM_ABI bool - compare_exchange_weak(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_compare_exchange_weak(std::addressof(__a_), std::addressof(__e), __d, __m, __m); - } - _LIBCPP_HIDE_FROM_ABI bool - compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); - } - _LIBCPP_HIDE_FROM_ABI bool - compare_exchange_strong(_Tp& __e, _Tp __d, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_compare_exchange_strong(std::addressof(__a_), std::addressof(__e), __d, __m, __m); - } - -#if _LIBCPP_STD_VER >= 20 - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void wait(_Tp __v, memory_order __m = memory_order_seq_cst) const - volatile _NOEXCEPT { - std::__atomic_wait(*this, __v, __m); - } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void - wait(_Tp __v, memory_order __m = memory_order_seq_cst) const _NOEXCEPT { - std::__atomic_wait(*this, __v, __m); - } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() volatile _NOEXCEPT { - std::__atomic_notify_one(*this); - } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_one() _NOEXCEPT { std::__atomic_notify_one(*this); } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() volatile _NOEXCEPT { - std::__atomic_notify_all(*this); - } - _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT { std::__atomic_notify_all(*this); } -#endif // _LIBCPP_STD_VER >= 20 - -#if _LIBCPP_STD_VER >= 20 - _LIBCPP_HIDE_FROM_ABI constexpr __atomic_base() noexcept(is_nothrow_default_constructible_v<_Tp>) : __a_(_Tp()) {} -#else - _LIBCPP_HIDE_FROM_ABI __atomic_base() _NOEXCEPT = default; -#endif - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __a_(__d) {} - - __atomic_base(const __atomic_base&) = delete; -}; - -// atomic - -template -struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { - using __base = __atomic_base<_Tp, false>; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default; - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {} - - _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_fetch_and(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_fetch_or(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT { - return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); - } - _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT { - return std::__cxx_atomic_fetch_xor(std::addressof(this->__a_), __op, __m); - } - - _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) volatile _NOEXCEPT { return fetch_add(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) _NOEXCEPT { return fetch_add(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) volatile _NOEXCEPT { return fetch_sub(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) _NOEXCEPT { return fetch_sub(_Tp(1)); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++() volatile _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator++() _NOEXCEPT { return fetch_add(_Tp(1)) + _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--() volatile _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator--() _NOEXCEPT { return fetch_sub(_Tp(1)) - _Tp(1); } - _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) _NOEXCEPT { return fetch_add(__op) + __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) _NOEXCEPT { return fetch_sub(__op) - __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) volatile _NOEXCEPT { return fetch_and(__op) & __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __op) _NOEXCEPT { return fetch_and(__op) & __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) volatile _NOEXCEPT { return fetch_or(__op) | __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __op) _NOEXCEPT { return fetch_or(__op) | __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) volatile _NOEXCEPT { return fetch_xor(__op) ^ __op; } - _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; } -}; - -// Here we need _IsIntegral because the default template argument is not enough -// e.g __atomic_base is __atomic_base, which inherits from -// __atomic_base and the caller of the wait function is -// __atomic_base. So specializing __atomic_base<_Tp> does not work -template -struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { - static _LIBCPP_HIDE_FROM_ABI _Tp __atomic_load(const __atomic_base<_Tp, _IsIntegral>& __a, memory_order __order) { - return __a.load(__order); - } - - static _LIBCPP_HIDE_FROM_ABI _Tp - __atomic_load(const volatile __atomic_base<_Tp, _IsIntegral>& __this, memory_order __order) { - return __this.load(__order); - } - - static _LIBCPP_HIDE_FROM_ABI const __cxx_atomic_impl<_Tp>* - __atomic_contention_address(const __atomic_base<_Tp, _IsIntegral>& __a) { - return std::addressof(__a.__a_); - } - - static _LIBCPP_HIDE_FROM_ABI const volatile __cxx_atomic_impl<_Tp>* - __atomic_contention_address(const volatile __atomic_base<_Tp, _IsIntegral>& __this) { - return std::addressof(__this.__a_); - } -}; - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___ATOMIC_ATOMIC_BASE_H diff --git a/libcxx/include/__chrono/convert_to_tm.h b/libcxx/include/__chrono/convert_to_tm.h index 5f1b2632f629a500e24e17b758a822798b45b316..46e3650e390ea64e6d0d6bb2ca12925829b8e446 100644 --- a/libcxx/include/__chrono/convert_to_tm.h +++ b/libcxx/include/__chrono/convert_to_tm.h @@ -116,7 +116,7 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) { return std::__convert_to_tm<_Tm>(chrono::sys_time{__value.time_since_epoch()}); else static_assert(sizeof(_ChronoT) == 0, "TODO: Add the missing clock specialization"); - } else if constexpr (chrono::__is_duration<_ChronoT>::value) { + } else if constexpr (chrono::__is_duration_v<_ChronoT>) { // [time.format]/6 // ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p, // etc.), then a specialization of duration is interpreted as the time of diff --git a/libcxx/include/__chrono/duration.h b/libcxx/include/__chrono/duration.h index 1e36d7342836f643c59eaee262f741576dbe6344..a401178b2a75c0aba6048e35489898441f8b7ca6 100644 --- a/libcxx/include/__chrono/duration.h +++ b/libcxx/include/__chrono/duration.h @@ -35,26 +35,25 @@ template > class _LIBCPP_TEMPLATE_VIS duration; template -struct __is_duration : false_type {}; +inline const bool __is_duration_v = false; template -struct __is_duration > : true_type {}; +inline const bool __is_duration_v > = true; template -struct __is_duration > : true_type {}; +inline const bool __is_duration_v > = true; template -struct __is_duration > : true_type {}; +inline const bool __is_duration_v > = true; template -struct __is_duration > : true_type {}; +inline const bool __is_duration_v > = true; } // namespace chrono template struct _LIBCPP_TEMPLATE_VIS common_type, chrono::duration<_Rep2, _Period2> > { - typedef chrono::duration::type, typename __ratio_gcd<_Period1, _Period2>::type> - type; + typedef chrono::duration::type, __ratio_gcd<_Period1, _Period2> > type; }; namespace chrono { @@ -102,7 +101,7 @@ struct __duration_cast<_FromDuration, _ToDuration, _Period, false, false> { } }; -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration duration_cast(const duration<_Rep, _Period>& __fd) { return __duration_cast, _ToDuration>()(__fd); } @@ -124,7 +123,7 @@ public: }; #if _LIBCPP_STD_VER >= 17 -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration<_Rep, _Period>& __d) { _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); if (__t > __d) @@ -132,7 +131,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration floor(const duration< return __t; } -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_Rep, _Period>& __d) { _ToDuration __t = chrono::duration_cast<_ToDuration>(__d); if (__t < __d) @@ -140,7 +139,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration ceil(const duration<_ return __t; } -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration<_Rep, _Period>& __d) { _ToDuration __lower = chrono::floor<_ToDuration>(__d); _ToDuration __upper = __lower + _ToDuration{1}; @@ -158,15 +157,15 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration< template class _LIBCPP_TEMPLATE_VIS duration { - static_assert(!__is_duration<_Rep>::value, "A duration representation can not be a duration"); - static_assert(__is_ratio<_Period>::value, "Second template parameter of duration must be a std::ratio"); + static_assert(!__is_duration_v<_Rep>, "A duration representation can not be a duration"); + static_assert(__is_ratio_v<_Period>, "Second template parameter of duration must be a std::ratio"); static_assert(_Period::num > 0, "duration period must be positive"); template struct __no_overflow { private: - static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; - static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; + static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>; + static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>; static const intmax_t __n1 = _R1::num / __gcd_n1_n2; static const intmax_t __d1 = _R1::den / __gcd_d1_d2; static const intmax_t __n2 = _R2::num / __gcd_n1_n2; @@ -434,7 +433,7 @@ operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) { template ::value && + __enable_if_t && is_convertible::type>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration::type, _Period> @@ -456,7 +455,7 @@ operator/(const duration<_Rep1, _Period1>& __lhs, const duration<_Rep2, _Period2 template ::value && + __enable_if_t && is_convertible::type>::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR duration::type, _Period> diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index c1b57209b938d96144510f9c1c6a2d2a40a36bb8..c579f03d729ce43811d4dc0a05e5416513befc89 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -159,7 +159,7 @@ consteval bool __use_fraction() { else if constexpr (__is_specialization_v<_Tp, chrono::zoned_time>) return chrono::hh_mm_ss::fractional_width; # endif - else if constexpr (chrono::__is_duration<_Tp>::value) + else if constexpr (chrono::__is_duration_v<_Tp>) return chrono::hh_mm_ss<_Tp>::fractional_width; else if constexpr (__is_hh_mm_ss<_Tp>) return _Tp::fractional_width; @@ -273,7 +273,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( } break; case _CharT('j'): - if constexpr (chrono::__is_duration<_Tp>::value) + if constexpr (chrono::__is_duration_v<_Tp>) // Converting a duration where the period has a small ratio to days // may fail to compile. This due to loss of precision in the // conversion. In order to avoid that issue convert to seconds as @@ -285,7 +285,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( break; case _CharT('q'): - if constexpr (chrono::__is_duration<_Tp>::value) { + if constexpr (chrono::__is_duration_v<_Tp>) { __sstr << chrono::__units_suffix<_CharT, typename _Tp::period>(); break; } @@ -301,7 +301,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs( // MSVC STL ignores precision but uses separator // FMT honours precision and has a bug for separator // https://godbolt.org/z/78b7sMxns - if constexpr (chrono::__is_duration<_Tp>::value) { + if constexpr (chrono::__is_duration_v<_Tp>) { __sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "{}"), __value.count()); break; } @@ -627,7 +627,7 @@ __format_chrono(const _Tp& __value, if (__chrono_specs.empty()) __sstr << __value; else { - if constexpr (chrono::__is_duration<_Tp>::value) { + if constexpr (chrono::__is_duration_v<_Tp>) { // A duration can be a user defined arithmetic type. Users may specialize // numeric_limits, but they may not specialize is_signed. if constexpr (numeric_limits::is_signed) { diff --git a/libcxx/include/__chrono/hh_mm_ss.h b/libcxx/include/__chrono/hh_mm_ss.h index 57d2247fe6a3c8c214603075b2f4c759725856d7..c460b113050859d0f092f590d112c57c0a24ff84 100644 --- a/libcxx/include/__chrono/hh_mm_ss.h +++ b/libcxx/include/__chrono/hh_mm_ss.h @@ -29,7 +29,7 @@ namespace chrono { template class hh_mm_ss { private: - static_assert(__is_duration<_Duration>::value, "template parameter of hh_mm_ss must be a std::chrono::duration"); + static_assert(__is_duration_v<_Duration>, "template parameter of hh_mm_ss must be a std::chrono::duration"); using __CommonType = common_type_t<_Duration, chrono::seconds>; _LIBCPP_HIDE_FROM_ABI static constexpr uint64_t __pow10(unsigned __exp) { diff --git a/libcxx/include/__chrono/time_point.h b/libcxx/include/__chrono/time_point.h index aaf0b098f280e00243bfcb4cd9355bd67c546f18..5e79fa5d257fa430f706c3ba24b2b09139c755da 100644 --- a/libcxx/include/__chrono/time_point.h +++ b/libcxx/include/__chrono/time_point.h @@ -32,8 +32,7 @@ namespace chrono { template class _LIBCPP_TEMPLATE_VIS time_point { - static_assert(__is_duration<_Duration>::value, - "Second template parameter of time_point must be a std::chrono::duration"); + static_assert(__is_duration_v<_Duration>, "Second template parameter of time_point must be a std::chrono::duration"); public: typedef _Clock clock; @@ -91,17 +90,17 @@ time_point_cast(const time_point<_Clock, _Duration>& __t) { } #if _LIBCPP_STD_VER >= 17 -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> floor(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>{chrono::floor<_ToDuration>(__t.time_since_epoch())}; } -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> ceil(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>{chrono::ceil<_ToDuration>(__t.time_since_epoch())}; } -template ::value, int> = 0> +template , int> = 0> inline _LIBCPP_HIDE_FROM_ABI constexpr time_point<_Clock, _ToDuration> round(const time_point<_Clock, _Duration>& __t) { return time_point<_Clock, _ToDuration>{chrono::round<_ToDuration>(__t.time_since_epoch())}; } diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h index 272fa047426758723da2d29572b79fec43fb362c..f57e65c90a624ec474ea7fe5d07efc7ab71cae58 100644 --- a/libcxx/include/__chrono/zoned_time.h +++ b/libcxx/include/__chrono/zoned_time.h @@ -58,7 +58,7 @@ struct zoned_traits { template class zoned_time { // [time.zone.zonedtime.ctor]/2 - static_assert(__is_duration<_Duration>::value, + static_assert(__is_duration_v<_Duration>, "the program is ill-formed since _Duration is not a specialization of std::chrono::duration"); // The wording uses the constraints like diff --git a/libcxx/include/__condition_variable/condition_variable.h b/libcxx/include/__condition_variable/condition_variable.h index 499e6f0f295dd3386295bb728a3a9152298083f8..4521fe274614ef287beb9bf4f3490dc60f56f097 100644 --- a/libcxx/include/__condition_variable/condition_variable.h +++ b/libcxx/include/__condition_variable/condition_variable.h @@ -16,7 +16,7 @@ #include <__config> #include <__mutex/mutex.h> #include <__mutex/unique_lock.h> -#include <__system_error/system_error.h> +#include <__system_error/throw_system_error.h> #include <__thread/support.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_floating_point.h> diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index 073b63cd8f0a661f663500090d96abba6cb2d245..58b362ad7a706f88b3305710a67ce3a1a58bfdab 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -113,7 +113,7 @@ public: class value_compare { private: key_compare __comp_; - value_compare(key_compare __c) : __comp_(__c) {} + _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {} friend flat_map; public: @@ -659,7 +659,7 @@ public: template requires __has_input_iterator_category<_InputIterator>::value - void insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { + _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) { if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) { __reserve(__last - __first); } diff --git a/libcxx/include/__iterator/ostreambuf_iterator.h b/libcxx/include/__iterator/ostreambuf_iterator.h index 621ffd4f988c31927c3717895e369a396cc5dc66..f00449355e4eb845658338fe9cf22d48207d53c1 100644 --- a/libcxx/include/__iterator/ostreambuf_iterator.h +++ b/libcxx/include/__iterator/ostreambuf_iterator.h @@ -65,9 +65,11 @@ public: _LIBCPP_HIDE_FROM_ABI ostreambuf_iterator& operator++(int) { return *this; } _LIBCPP_HIDE_FROM_ABI bool failed() const _NOEXCEPT { return __sbuf_ == nullptr; } +#if _LIBCPP_HAS_LOCALIZATION template friend _LIBCPP_HIDE_FROM_ABI ostreambuf_iterator<_Ch, _Tr> __pad_and_output( ostreambuf_iterator<_Ch, _Tr> __s, const _Ch* __ob, const _Ch* __op, const _Ch* __oe, ios_base& __iob, _Ch __fl); +#endif // _LIBCPP_HAS_LOCALIZATION }; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__locale b/libcxx/include/__locale index b07b9f3329f42ce3a0f63556b73e2bcab9e05e20..b675e01bac81e5206c8681c7706a8915f8440b03 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -12,7 +12,7 @@ #include <__config> #include <__locale_dir/locale_base_api.h> -#include <__memory/shared_ptr.h> // __shared_count +#include <__memory/shared_count.h> #include <__mutex/once_flag.h> #include <__type_traits/make_unsigned.h> #include <__utility/no_destroy.h> diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h index 5cbe91207ca74e4c039d15176bde44013feb33e8..8ed4c29cb8732ff79c7270eeed1061b180e97b92 100644 --- a/libcxx/include/__locale_dir/locale_base_api.h +++ b/libcxx/include/__locale_dir/locale_base_api.h @@ -265,17 +265,17 @@ _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") // GCC doesn't support [[g template _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf( char* __s, size_t __n, __locale_t __loc, const char* __format, _Args&&... __args) { - return __libcpp_snprintf_l(__s, __n, __loc, __format, std::forward<_Args>(__args)...); + return std::__libcpp_snprintf_l(__s, __n, __loc, __format, std::forward<_Args>(__args)...); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 3, 4) int __asprintf( char** __s, __locale_t __loc, const char* __format, _Args&&... __args) { - return __libcpp_asprintf_l(__s, __loc, __format, std::forward<_Args>(__args)...); + return std::__libcpp_asprintf_l(__s, __loc, __format, std::forward<_Args>(__args)...); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __sscanf( const char* __s, __locale_t __loc, const char* __format, _Args&&... __args) { - return __libcpp_sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...); + return std::__libcpp_sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...); } _LIBCPP_DIAGNOSTIC_POP # undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT diff --git a/libcxx/include/__locale_dir/pad_and_output.h b/libcxx/include/__locale_dir/pad_and_output.h new file mode 100644 index 0000000000000000000000000000000000000000..a1cb37d0786dabaf8b033dbf8a51dbd761e32d1b --- /dev/null +++ b/libcxx/include/__locale_dir/pad_and_output.h @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// 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___LOCALE_DIR_PAD_AND_OUTPUT_H +#define _LIBCPP___LOCALE_DIR_PAD_AND_OUTPUT_H + +#include <__config> + +#if _LIBCPP_HAS_LOCALIZATION + +# include + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _OutputIterator __pad_and_output( + _OutputIterator __s, const _CharT* __ob, const _CharT* __op, const _CharT* __oe, ios_base& __iob, _CharT __fl) { + streamsize __sz = __oe - __ob; + streamsize __ns = __iob.width(); + if (__ns > __sz) + __ns -= __sz; + else + __ns = 0; + for (; __ob < __op; ++__ob, ++__s) + *__s = *__ob; + for (; __ns; --__ns, ++__s) + *__s = __fl; + for (; __ob < __oe; ++__ob, ++__s) + *__s = *__ob; + __iob.width(0); + return __s; +} + +template +_LIBCPP_HIDE_FROM_ABI ostreambuf_iterator<_CharT, _Traits> __pad_and_output( + ostreambuf_iterator<_CharT, _Traits> __s, + const _CharT* __ob, + const _CharT* __op, + const _CharT* __oe, + ios_base& __iob, + _CharT __fl) { + if (__s.__sbuf_ == nullptr) + return __s; + streamsize __sz = __oe - __ob; + streamsize __ns = __iob.width(); + if (__ns > __sz) + __ns -= __sz; + else + __ns = 0; + streamsize __np = __op - __ob; + if (__np > 0) { + if (__s.__sbuf_->sputn(__ob, __np) != __np) { + __s.__sbuf_ = nullptr; + return __s; + } + } + if (__ns > 0) { + basic_string<_CharT, _Traits> __sp(__ns, __fl); + if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns) { + __s.__sbuf_ = nullptr; + return __s; + } + } + __np = __oe - __op; + if (__np > 0) { + if (__s.__sbuf_->sputn(__op, __np) != __np) { + __s.__sbuf_ = nullptr; + return __s; + } + } + __iob.width(0); + return __s; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_PAD_AND_OUTPUT_H diff --git a/libcxx/include/__memory/allocator_arg_t.h b/libcxx/include/__memory/allocator_arg_t.h index 7e66da740cd4fd8f0435fa91175dbae13c188274..dc4398bb02d349ef2c62cbd6c84e0e4c56a94bbc 100644 --- a/libcxx/include/__memory/allocator_arg_t.h +++ b/libcxx/include/__memory/allocator_arg_t.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___FUNCTIONAL_ALLOCATOR_ARG_T_H -#define _LIBCPP___FUNCTIONAL_ALLOCATOR_ARG_T_H +#ifndef _LIBCPP___MEMORY_ALLOCATOR_ARG_T_H +#define _LIBCPP___MEMORY_ALLOCATOR_ARG_T_H #include <__config> #include <__memory/uses_allocator.h> @@ -72,4 +72,4 @@ __user_alloc_construct_impl(integral_constant, _Tp* __storage, const _Al _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___FUNCTIONAL_ALLOCATOR_ARG_T_H +#endif // _LIBCPP___MEMORY_ALLOCATOR_ARG_T_H diff --git a/libcxx/include/__memory/shared_count.h b/libcxx/include/__memory/shared_count.h new file mode 100644 index 0000000000000000000000000000000000000000..1438c6ba5a6d29ca0b98d64790be00fbde078ed7 --- /dev/null +++ b/libcxx/include/__memory/shared_count.h @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// 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___MEMORY_SHARED_COUNT_H +#define _LIBCPP___MEMORY_SHARED_COUNT_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively) +// should be sufficient for thread safety. +// See https://llvm.org/PR22803 +#if (defined(__clang__) && __has_builtin(__atomic_add_fetch) && defined(__ATOMIC_RELAXED) && \ + defined(__ATOMIC_ACQ_REL)) || \ + defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT 1 +#else +# define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT 0 +#endif + +template +inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_relaxed_load(_ValueType const* __value) { +#if _LIBCPP_HAS_THREADS && defined(__ATOMIC_RELAXED) && \ + (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) + return __atomic_load_n(__value, __ATOMIC_RELAXED); +#else + return *__value; +#endif +} + +template +inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_acquire_load(_ValueType const* __value) { +#if _LIBCPP_HAS_THREADS && defined(__ATOMIC_ACQUIRE) && \ + (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) + return __atomic_load_n(__value, __ATOMIC_ACQUIRE); +#else + return *__value; +#endif +} + +template +inline _LIBCPP_HIDE_FROM_ABI _Tp __libcpp_atomic_refcount_increment(_Tp& __t) _NOEXCEPT { +#if _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT && _LIBCPP_HAS_THREADS + return __atomic_add_fetch(&__t, 1, __ATOMIC_RELAXED); +#else + return __t += 1; +#endif +} + +template +inline _LIBCPP_HIDE_FROM_ABI _Tp __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT { +#if _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT && _LIBCPP_HAS_THREADS + return __atomic_add_fetch(&__t, -1, __ATOMIC_ACQ_REL); +#else + return __t -= 1; +#endif +} + +class _LIBCPP_EXPORTED_FROM_ABI __shared_count { + __shared_count(const __shared_count&); + __shared_count& operator=(const __shared_count&); + +protected: + long __shared_owners_; + virtual ~__shared_count(); + +private: + virtual void __on_zero_shared() _NOEXCEPT = 0; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __shared_count(long __refs = 0) _NOEXCEPT : __shared_owners_(__refs) {} + +#if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS) + void __add_shared() noexcept; + bool __release_shared() noexcept; +#else + _LIBCPP_HIDE_FROM_ABI void __add_shared() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_owners_); } + _LIBCPP_HIDE_FROM_ABI bool __release_shared() _NOEXCEPT { + if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { + __on_zero_shared(); + return true; + } + return false; + } +#endif + _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __libcpp_relaxed_load(&__shared_owners_) + 1; } +}; + +class _LIBCPP_EXPORTED_FROM_ABI __shared_weak_count : private __shared_count { + long __shared_weak_owners_; + +public: + _LIBCPP_HIDE_FROM_ABI explicit __shared_weak_count(long __refs = 0) _NOEXCEPT + : __shared_count(__refs), + __shared_weak_owners_(__refs) {} + +protected: + ~__shared_weak_count() override; + +public: +#if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS) + void __add_shared() noexcept; + void __add_weak() noexcept; + void __release_shared() noexcept; +#else + _LIBCPP_HIDE_FROM_ABI void __add_shared() _NOEXCEPT { __shared_count::__add_shared(); } + _LIBCPP_HIDE_FROM_ABI void __add_weak() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_weak_owners_); } + _LIBCPP_HIDE_FROM_ABI void __release_shared() _NOEXCEPT { + if (__shared_count::__release_shared()) + __release_weak(); + } +#endif + void __release_weak() _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __shared_count::use_count(); } + __shared_weak_count* lock() _NOEXCEPT; + + virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; + +private: + virtual void __on_zero_shared_weak() _NOEXCEPT = 0; +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_SHARED_COUNT_H diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 5a84c2ce9bfe1792bf679cb0fd90375b51f0873d..5c34f2efc5730e3903284b8a371e2ac3b5b0b733 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -30,6 +30,7 @@ #include <__memory/compressed_pair.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> +#include <__memory/shared_count.h> #include <__memory/uninitialized_algorithms.h> #include <__memory/unique_ptr.h> #include <__type_traits/add_lvalue_reference.h> @@ -70,55 +71,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -// NOTE: Relaxed and acq/rel atomics (for increment and decrement respectively) -// should be sufficient for thread safety. -// See https://llvm.org/PR22803 -#if (defined(__clang__) && __has_builtin(__atomic_add_fetch) && defined(__ATOMIC_RELAXED) && \ - defined(__ATOMIC_ACQ_REL)) || \ - defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT 1 -#else -# define _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT 0 -#endif - -template -inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_relaxed_load(_ValueType const* __value) { -#if _LIBCPP_HAS_THREADS && defined(__ATOMIC_RELAXED) && \ - (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) - return __atomic_load_n(__value, __ATOMIC_RELAXED); -#else - return *__value; -#endif -} - -template -inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_acquire_load(_ValueType const* __value) { -#if _LIBCPP_HAS_THREADS && defined(__ATOMIC_ACQUIRE) && \ - (__has_builtin(__atomic_load_n) || defined(_LIBCPP_COMPILER_GCC)) - return __atomic_load_n(__value, __ATOMIC_ACQUIRE); -#else - return *__value; -#endif -} - -template -inline _LIBCPP_HIDE_FROM_ABI _Tp __libcpp_atomic_refcount_increment(_Tp& __t) _NOEXCEPT { -#if _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT && _LIBCPP_HAS_THREADS - return __atomic_add_fetch(&__t, 1, __ATOMIC_RELAXED); -#else - return __t += 1; -#endif -} - -template -inline _LIBCPP_HIDE_FROM_ABI _Tp __libcpp_atomic_refcount_decrement(_Tp& __t) _NOEXCEPT { -#if _LIBCPP_HAS_BUILTIN_ATOMIC_SUPPORT && _LIBCPP_HAS_THREADS - return __atomic_add_fetch(&__t, -1, __ATOMIC_ACQ_REL); -#else - return __t -= 1; -#endif -} - class _LIBCPP_EXPORTED_FROM_ABI bad_weak_ptr : public std::exception { public: _LIBCPP_HIDE_FROM_ABI bad_weak_ptr() _NOEXCEPT = default; @@ -139,70 +91,6 @@ public: template class _LIBCPP_TEMPLATE_VIS weak_ptr; -class _LIBCPP_EXPORTED_FROM_ABI __shared_count { - __shared_count(const __shared_count&); - __shared_count& operator=(const __shared_count&); - -protected: - long __shared_owners_; - virtual ~__shared_count(); - -private: - virtual void __on_zero_shared() _NOEXCEPT = 0; - -public: - _LIBCPP_HIDE_FROM_ABI explicit __shared_count(long __refs = 0) _NOEXCEPT : __shared_owners_(__refs) {} - -#if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS) - void __add_shared() noexcept; - bool __release_shared() noexcept; -#else - _LIBCPP_HIDE_FROM_ABI void __add_shared() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_owners_); } - _LIBCPP_HIDE_FROM_ABI bool __release_shared() _NOEXCEPT { - if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) { - __on_zero_shared(); - return true; - } - return false; - } -#endif - _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __libcpp_relaxed_load(&__shared_owners_) + 1; } -}; - -class _LIBCPP_EXPORTED_FROM_ABI __shared_weak_count : private __shared_count { - long __shared_weak_owners_; - -public: - _LIBCPP_HIDE_FROM_ABI explicit __shared_weak_count(long __refs = 0) _NOEXCEPT - : __shared_count(__refs), - __shared_weak_owners_(__refs) {} - -protected: - ~__shared_weak_count() override; - -public: -#if defined(_LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS) - void __add_shared() noexcept; - void __add_weak() noexcept; - void __release_shared() noexcept; -#else - _LIBCPP_HIDE_FROM_ABI void __add_shared() _NOEXCEPT { __shared_count::__add_shared(); } - _LIBCPP_HIDE_FROM_ABI void __add_weak() _NOEXCEPT { __libcpp_atomic_refcount_increment(__shared_weak_owners_); } - _LIBCPP_HIDE_FROM_ABI void __release_shared() _NOEXCEPT { - if (__shared_count::__release_shared()) - __release_weak(); - } -#endif - void __release_weak() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI long use_count() const _NOEXCEPT { return __shared_count::use_count(); } - __shared_weak_count* lock() _NOEXCEPT; - - virtual const void* __get_deleter(const type_info&) const _NOEXCEPT; - -private: - virtual void __on_zero_shared_weak() _NOEXCEPT = 0; -}; - template class __shared_ptr_pointer : public __shared_weak_count { _LIBCPP_COMPRESSED_TRIPLE(_Tp, __ptr_, _Dp, __deleter_, _Alloc, __alloc_); diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 627ee44e808d9c50493e295efac0e8e70fcadfb9..71c7ed94fec13e3b34eec208faa5ebeeffd96049 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -612,26 +612,28 @@ struct __allocator_has_trivial_destroy, _Up> : true_type {}; // [__first, __last) doesn't contain any objects // // The strong exception guarantee is provided if any of the following are true: -// - is_nothrow_move_constructible<_Tp> -// - is_copy_constructible<_Tp> -// - __libcpp_is_trivially_relocatable<_Tp> -template -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void -__uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _Tp* __result) { +// - is_nothrow_move_constructible<_ValueType> +// - is_copy_constructible<_ValueType> +// - __libcpp_is_trivially_relocatable<_ValueType> +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __uninitialized_allocator_relocate( + _Alloc& __alloc, _ContiguousIterator __first, _ContiguousIterator __last, _ContiguousIterator __result) { + static_assert(__libcpp_is_contiguous_iterator<_ContiguousIterator>::value, ""); + using _ValueType = typename iterator_traits<_ContiguousIterator>::value_type; static_assert(__is_cpp17_move_insertable<_Alloc>::value, "The specified type does not meet the requirements of Cpp17MoveInsertable"); - if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_Tp>::value || - !__allocator_has_trivial_move_construct<_Alloc, _Tp>::value || - !__allocator_has_trivial_destroy<_Alloc, _Tp>::value) { + if (__libcpp_is_constant_evaluated() || !__libcpp_is_trivially_relocatable<_ValueType>::value || + !__allocator_has_trivial_move_construct<_Alloc, _ValueType>::value || + !__allocator_has_trivial_destroy<_Alloc, _ValueType>::value) { auto __destruct_first = __result; - auto __guard = - std::__make_exception_guard(_AllocatorDestroyRangeReverse<_Alloc, _Tp*>(__alloc, __destruct_first, __result)); + auto __guard = std::__make_exception_guard( + _AllocatorDestroyRangeReverse<_Alloc, _ContiguousIterator>(__alloc, __destruct_first, __result)); auto __iter = __first; while (__iter != __last) { #if _LIBCPP_HAS_EXCEPTIONS - allocator_traits<_Alloc>::construct(__alloc, __result, std::move_if_noexcept(*__iter)); + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move_if_noexcept(*__iter)); #else - allocator_traits<_Alloc>::construct(__alloc, __result, std::move(*__iter)); + allocator_traits<_Alloc>::construct(__alloc, std::__to_address(__result), std::move(*__iter)); #endif ++__iter; ++__result; @@ -640,7 +642,9 @@ __uninitialized_allocator_relocate(_Alloc& __alloc, _Tp* __first, _Tp* __last, _ std::__allocator_destroy(__alloc, __first, __last); } else { // Casting to void* to suppress clang complaining that this is technically UB. - __builtin_memcpy(static_cast(__result), __first, sizeof(_Tp) * (__last - __first)); + __builtin_memcpy(static_cast(std::__to_address(__result)), + std::__to_address(__first), + sizeof(_ValueType) * (__last - __first)); } } diff --git a/libcxx/include/__mutex/once_flag.h b/libcxx/include/__mutex/once_flag.h index 9d7baecbc708590dcd86fb8ae14b879e480606e3..08ff54bf99265ea154fc09faf7618fade97dc3f9 100644 --- a/libcxx/include/__mutex/once_flag.h +++ b/libcxx/include/__mutex/once_flag.h @@ -11,7 +11,7 @@ #include <__config> #include <__functional/invoke.h> -#include <__memory/shared_ptr.h> // __libcpp_acquire_load +#include <__memory/shared_count.h> // __libcpp_acquire_load #include <__tuple/tuple_indices.h> #include <__tuple/tuple_size.h> #include <__utility/forward.h> diff --git a/libcxx/include/__mutex/unique_lock.h b/libcxx/include/__mutex/unique_lock.h index c404921070f9133196536fc962dadccb07defeac..3642ab93cb1f7cbae971fb705fcee5ad0828c49b 100644 --- a/libcxx/include/__mutex/unique_lock.h +++ b/libcxx/include/__mutex/unique_lock.h @@ -14,7 +14,7 @@ #include <__config> #include <__memory/addressof.h> #include <__mutex/tag_types.h> -#include <__system_error/system_error.h> +#include <__system_error/throw_system_error.h> #include <__utility/swap.h> #include diff --git a/libcxx/include/__ostream/basic_ostream.h b/libcxx/include/__ostream/basic_ostream.h index c37566d2356cafc3ba64b00aa31935d0298b7e6d..ad43c72a3c2eae52c98606f8127fda288c8b7417 100644 --- a/libcxx/include/__ostream/basic_ostream.h +++ b/libcxx/include/__ostream/basic_ostream.h @@ -16,6 +16,7 @@ # include <__exception/operations.h> # include <__memory/shared_ptr.h> # include <__memory/unique_ptr.h> +# include <__ostream/put_character_sequence.h> # include <__system_error/error_code.h> # include <__type_traits/conjunction.h> # include <__type_traits/enable_if.h> @@ -496,33 +497,6 @@ basic_ostream<_CharT, _Traits>& basic_ostream<_CharT, _Traits>::operator<<(const return *this; } -template -_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& -__put_character_sequence(basic_ostream<_CharT, _Traits>& __os, const _CharT* __str, size_t __len) { -# if _LIBCPP_HAS_EXCEPTIONS - try { -# endif // _LIBCPP_HAS_EXCEPTIONS - typename basic_ostream<_CharT, _Traits>::sentry __s(__os); - if (__s) { - typedef ostreambuf_iterator<_CharT, _Traits> _Ip; - if (std::__pad_and_output( - _Ip(__os), - __str, - (__os.flags() & ios_base::adjustfield) == ios_base::left ? __str + __len : __str, - __str + __len, - __os, - __os.fill()) - .failed()) - __os.setstate(ios_base::badbit | ios_base::failbit); - } -# if _LIBCPP_HAS_EXCEPTIONS - } catch (...) { - __os.__set_badbit_and_consider_rethrow(); - } -# endif // _LIBCPP_HAS_EXCEPTIONS - return __os; -} - template _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, _CharT __c) { return std::__put_character_sequence(__os, &__c, 1); diff --git a/libcxx/include/__ostream/put_character_sequence.h b/libcxx/include/__ostream/put_character_sequence.h new file mode 100644 index 0000000000000000000000000000000000000000..aa771b34d58b5f80a8944cd158235ebb5ab29973 --- /dev/null +++ b/libcxx/include/__ostream/put_character_sequence.h @@ -0,0 +1,59 @@ +//===---------------------------------------------------------------------===// +// +// 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___OSTREAM_PUT_CHARACTER_SEQUENCE_H +#define _LIBCPP___OSTREAM_PUT_CHARACTER_SEQUENCE_H + +#include <__config> + +#if _LIBCPP_HAS_LOCALIZATION + +# include <__cstddef/size_t.h> +# include <__fwd/ostream.h> +# include <__iterator/ostreambuf_iterator.h> +# include <__locale_dir/pad_and_output.h> +# include + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& +__put_character_sequence(basic_ostream<_CharT, _Traits>& __os, const _CharT* __str, size_t __len) { +# if _LIBCPP_HAS_EXCEPTIONS + try { +# endif // _LIBCPP_HAS_EXCEPTIONS + typename basic_ostream<_CharT, _Traits>::sentry __s(__os); + if (__s) { + typedef ostreambuf_iterator<_CharT, _Traits> _Ip; + if (std::__pad_and_output( + _Ip(__os), + __str, + (__os.flags() & ios_base::adjustfield) == ios_base::left ? __str + __len : __str, + __str + __len, + __os, + __os.fill()) + .failed()) + __os.setstate(ios_base::badbit | ios_base::failbit); + } +# if _LIBCPP_HAS_EXCEPTIONS + } catch (...) { + __os.__set_badbit_and_consider_rethrow(); + } +# endif // _LIBCPP_HAS_EXCEPTIONS + return __os; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___OSTREAM_PUT_CHARACTER_SEQUENCE_H diff --git a/libcxx/include/__random/discard_block_engine.h b/libcxx/include/__random/discard_block_engine.h index f319557a57365792e1d7d4ec40a13f901a3eecc8..45951245a534010879777e46ebe36eda4fa04922 100644 --- a/libcxx/include/__random/discard_block_engine.h +++ b/libcxx/include/__random/discard_block_engine.h @@ -43,8 +43,8 @@ public: typedef typename _Engine::result_type result_type; // engine characteristics - static _LIBCPP_CONSTEXPR const size_t block_size = __p; - static _LIBCPP_CONSTEXPR const size_t used_block = __r; + static inline _LIBCPP_CONSTEXPR const size_t block_size = __p; + static inline _LIBCPP_CONSTEXPR const size_t used_block = __r; #ifdef _LIBCPP_CXX03_LANG static const result_type _Min = _Engine::_Min; @@ -110,12 +110,6 @@ public: operator>>(basic_istream<_CharT, _Traits>& __is, discard_block_engine<_Eng, _Pp, _Rp>& __x); }; -template -_LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::block_size; - -template -_LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::used_block; - template typename discard_block_engine<_Engine, __p, __r>::result_type discard_block_engine<_Engine, __p, __r>::operator()() { if (__n_ >= static_cast(__r)) { diff --git a/libcxx/include/__random/linear_congruential_engine.h b/libcxx/include/__random/linear_congruential_engine.h index a0afda4945cdcf244ddafb7bfde6d0934ca22a9c..a6e63839d3fc1640d31cdab777fdfffc3520ac71 100644 --- a/libcxx/include/__random/linear_congruential_engine.h +++ b/libcxx/include/__random/linear_congruential_engine.h @@ -251,12 +251,12 @@ public: static_assert(_Min < _Max, "linear_congruential_engine invalid parameters"); // engine characteristics - static _LIBCPP_CONSTEXPR const result_type multiplier = __a; - static _LIBCPP_CONSTEXPR const result_type increment = __c; - static _LIBCPP_CONSTEXPR const result_type modulus = __m; + static inline _LIBCPP_CONSTEXPR const result_type multiplier = __a; + static inline _LIBCPP_CONSTEXPR const result_type increment = __c; + static inline _LIBCPP_CONSTEXPR const result_type modulus = __m; _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; } _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; } - static _LIBCPP_CONSTEXPR const result_type default_seed = 1u; + static inline _LIBCPP_CONSTEXPR const result_type default_seed = 1u; // constructors and seeding functions #ifndef _LIBCPP_CXX03_LANG @@ -318,22 +318,6 @@ private: operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x); }; -template -_LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type - linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier; - -template -_LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type - linear_congruential_engine<_UIntType, __a, __c, __m>::increment; - -template -_LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type - linear_congruential_engine<_UIntType, __a, __c, __m>::modulus; - -template -_LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type - linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed; - template template void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant) { diff --git a/libcxx/include/__random/mersenne_twister_engine.h b/libcxx/include/__random/mersenne_twister_engine.h index 9dd87f9ce71a115b7e1ab279538951e631fe4aae..a23feffff0c89c97913462f94c0313a3dbfa2b93 100644 --- a/libcxx/include/__random/mersenne_twister_engine.h +++ b/libcxx/include/__random/mersenne_twister_engine.h @@ -166,22 +166,22 @@ public: static_assert(__f <= _Max, "mersenne_twister_engine invalid parameters"); // engine characteristics - static _LIBCPP_CONSTEXPR const size_t word_size = __w; - static _LIBCPP_CONSTEXPR const size_t state_size = __n; - static _LIBCPP_CONSTEXPR const size_t shift_size = __m; - static _LIBCPP_CONSTEXPR const size_t mask_bits = __r; - static _LIBCPP_CONSTEXPR const result_type xor_mask = __a; - static _LIBCPP_CONSTEXPR const size_t tempering_u = __u; - static _LIBCPP_CONSTEXPR const result_type tempering_d = __d; - static _LIBCPP_CONSTEXPR const size_t tempering_s = __s; - static _LIBCPP_CONSTEXPR const result_type tempering_b = __b; - static _LIBCPP_CONSTEXPR const size_t tempering_t = __t; - static _LIBCPP_CONSTEXPR const result_type tempering_c = __c; - static _LIBCPP_CONSTEXPR const size_t tempering_l = __l; - static _LIBCPP_CONSTEXPR const result_type initialization_multiplier = __f; + static inline _LIBCPP_CONSTEXPR const size_t word_size = __w; + static inline _LIBCPP_CONSTEXPR const size_t state_size = __n; + static inline _LIBCPP_CONSTEXPR const size_t shift_size = __m; + static inline _LIBCPP_CONSTEXPR const size_t mask_bits = __r; + static inline _LIBCPP_CONSTEXPR const result_type xor_mask = __a; + static inline _LIBCPP_CONSTEXPR const size_t tempering_u = __u; + static inline _LIBCPP_CONSTEXPR const result_type tempering_d = __d; + static inline _LIBCPP_CONSTEXPR const size_t tempering_s = __s; + static inline _LIBCPP_CONSTEXPR const result_type tempering_b = __b; + static inline _LIBCPP_CONSTEXPR const size_t tempering_t = __t; + static inline _LIBCPP_CONSTEXPR const result_type tempering_c = __c; + static inline _LIBCPP_CONSTEXPR const size_t tempering_l = __l; + static inline _LIBCPP_CONSTEXPR const result_type initialization_multiplier = __f; _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; } _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; } - static _LIBCPP_CONSTEXPR const result_type default_seed = 5489u; + static inline _LIBCPP_CONSTEXPR const result_type default_seed = 5489u; // constructors and seeding functions #ifndef _LIBCPP_CXX03_LANG @@ -310,329 +310,6 @@ private: } }; -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::word_size; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::state_size; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::shift_size; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::mask_bits; - -template -_LIBCPP_CONSTEXPR const typename mersenne_twister_engine< - _UIntType, - __w, - __n, - __m, - __r, - __a, - __u, - __d, - __s, - __b, - __t, - __c, - __l, - __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::xor_mask; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_u; - -template -_LIBCPP_CONSTEXPR const typename mersenne_twister_engine< - _UIntType, - __w, - __n, - __m, - __r, - __a, - __u, - __d, - __s, - __b, - __t, - __c, - __l, - __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_d; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_s; - -template -_LIBCPP_CONSTEXPR const typename mersenne_twister_engine< - _UIntType, - __w, - __n, - __m, - __r, - __a, - __u, - __d, - __s, - __b, - __t, - __c, - __l, - __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_b; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_t; - -template -_LIBCPP_CONSTEXPR const typename mersenne_twister_engine< - _UIntType, - __w, - __n, - __m, - __r, - __a, - __u, - __d, - __s, - __b, - __t, - __c, - __l, - __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_c; - -template -_LIBCPP_CONSTEXPR const size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::tempering_l; - -template -_LIBCPP_CONSTEXPR const typename mersenne_twister_engine< - _UIntType, - __w, - __n, - __m, - __r, - __a, - __u, - __d, - __s, - __b, - __t, - __c, - __l, - __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>:: - initialization_multiplier; - -template -_LIBCPP_CONSTEXPR const typename mersenne_twister_engine< - _UIntType, - __w, - __n, - __m, - __r, - __a, - __u, - __d, - __s, - __b, - __t, - __c, - __l, - __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>::default_seed; - template -_LIBCPP_CONSTEXPR const size_t shuffle_order_engine<_Engine, __k>::table_size; - template _LIBCPP_HIDE_FROM_ABI bool operator==(const shuffle_order_engine<_Eng, _Kp>& __x, const shuffle_order_engine<_Eng, _Kp>& __y) { diff --git a/libcxx/include/__random/subtract_with_carry_engine.h b/libcxx/include/__random/subtract_with_carry_engine.h index e087ab4a3c2c7bb51b9a1273f555b401b9186b58..40dfaf4016ada0c5b3430611bfd4ca914f50f902 100644 --- a/libcxx/include/__random/subtract_with_carry_engine.h +++ b/libcxx/include/__random/subtract_with_carry_engine.h @@ -72,12 +72,12 @@ public: static_assert(_Min < _Max, "subtract_with_carry_engine invalid parameters"); // engine characteristics - static _LIBCPP_CONSTEXPR const size_t word_size = __w; - static _LIBCPP_CONSTEXPR const size_t short_lag = __s; - static _LIBCPP_CONSTEXPR const size_t long_lag = __r; + static inline _LIBCPP_CONSTEXPR const size_t word_size = __w; + static inline _LIBCPP_CONSTEXPR const size_t short_lag = __s; + static inline _LIBCPP_CONSTEXPR const size_t long_lag = __r; _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; } _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; } - static _LIBCPP_CONSTEXPR const result_type default_seed = 19780503u; + static inline _LIBCPP_CONSTEXPR const result_type default_seed = 19780503u; // constructors and seeding functions #ifndef _LIBCPP_CXX03_LANG @@ -130,19 +130,6 @@ private: _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant); }; -template -_LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size; - -template -_LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::short_lag; - -template -_LIBCPP_CONSTEXPR const size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag; - -template -_LIBCPP_CONSTEXPR const typename subtract_with_carry_engine<_UIntType, __w, __s, __r>::result_type - subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed; - template void subtract_with_carry_engine<_UIntType, __w, __s, __r>::seed(result_type __sd, integral_constant) { linear_congruential_engine __e(__sd == 0u ? default_seed : __sd); diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h index 76249bdd9891c8d68a81fa65851e784ea05dea83..c937b0656de87d456f35a48a9d72e72a8ae055ba 100644 --- a/libcxx/include/__ranges/to.h +++ b/libcxx/include/__ranges/to.h @@ -111,14 +111,14 @@ template for (auto&& __ref : __range) { using _Ref = decltype(__ref); - if constexpr (requires { __result.emplace_back(declval<_Ref>()); }) { + if constexpr (requires { __result.emplace_back(std::declval<_Ref>()); }) { __result.emplace_back(std::forward<_Ref>(__ref)); - } else if constexpr (requires { __result.push_back(declval<_Ref>()); }) { + } else if constexpr (requires { __result.push_back(std::declval<_Ref>()); }) { __result.push_back(std::forward<_Ref>(__ref)); - } else if constexpr (requires { __result.emplace(__result.end(), declval<_Ref>()); }) { + } else if constexpr (requires { __result.emplace(__result.end(), std::declval<_Ref>()); }) { __result.emplace(__result.end(), std::forward<_Ref>(__ref)); } else { - static_assert(requires { __result.insert(__result.end(), declval<_Ref>()); }); + static_assert(requires { __result.insert(__result.end(), std::declval<_Ref>()); }); __result.insert(__result.end(), std::forward<_Ref>(__ref)); } } diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index 2a2f2625c748b2feebfdb2ec0dd5f917e9fa6044..a44811c766735ab8abd52ee3b8f043fa7be949e9 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -47,7 +47,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD // __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_). -// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __end_cap_.first()). That allows +// It has uninitialized memory in the ranges [__first_, __begin_) and [__end_, __cap_). That allows // it to grow both in the front and back without having to move the data. template > @@ -78,20 +78,20 @@ public: pointer __first_; pointer __begin_; pointer __end_; - _LIBCPP_COMPRESSED_PAIR(pointer, __end_cap_, allocator_type, __alloc_); + _LIBCPP_COMPRESSED_PAIR(pointer, __cap_, allocator_type, __alloc_); __split_buffer(const __split_buffer&) = delete; __split_buffer& operator=(const __split_buffer&) = delete; _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer() _NOEXCEPT_(is_nothrow_default_constructible::value) - : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr) {} + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a) - : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr), __alloc_(__a) {} + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a) - : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr), __alloc_(__a) {} + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __cap_(nullptr), __alloc_(__a) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); @@ -123,7 +123,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const { - return static_cast(__end_cap_ - __first_); + return static_cast(__cap_ - __first_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const { @@ -131,7 +131,7 @@ public: } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const { - return static_cast(__end_cap_ - __end_); + return static_cast(__cap_ - __end_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; } @@ -139,7 +139,6 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return *(__end_ - 1); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return *(__end_ - 1); } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; template @@ -153,9 +152,6 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x); - template ::value, int> = 0> - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_InputIter __first, _InputIter __last); - template ::value, int> = 0> _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); @@ -219,14 +215,14 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants return false; if (__end_ != nullptr) return false; - if (__end_cap_ != nullptr) + if (__cap_ != nullptr) return false; } else { if (__begin_ < __first_) return false; if (__end_ < __begin_) return false; - if (__end_cap_ < __end_) + if (__cap_ < __end_) return false; } return true; @@ -260,21 +256,14 @@ __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_referen } } -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 void -__split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) { - __construct_at_end_with_sentinel(__first, __last); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) { __alloc_rr& __a = __alloc_; for (; __first != __last; ++__first) { - if (__end_ == __end_cap_) { - size_type __old_cap = __end_cap_ - __first_; + if (__end_ == __cap_) { + size_type __old_cap = __cap_ - __first_; size_type __new_cap = std::max(2 * __old_cap, 8); __split_buffer __buf(__new_cap, 0, __a); for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_) @@ -331,7 +320,7 @@ __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type template _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) - : __end_cap_(nullptr), __alloc_(__a) { + : __cap_(nullptr), __alloc_(__a) { if (__cap == 0) { __first_ = nullptr; } else { @@ -340,7 +329,7 @@ __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __sta __cap = __allocation.count; } __begin_ = __end_ = __first_ + __start; - __end_cap_ = __first_ + __cap; + __cap_ = __first_ + __cap; } template @@ -356,32 +345,32 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__ : __first_(std::move(__c.__first_)), __begin_(std::move(__c.__begin_)), __end_(std::move(__c.__end_)), - __end_cap_(std::move(__c.__end_cap_)), + __cap_(std::move(__c.__cap_)), __alloc_(std::move(__c.__alloc_)) { - __c.__first_ = nullptr; - __c.__begin_ = nullptr; - __c.__end_ = nullptr; - __c.__end_cap_ = nullptr; + __c.__first_ = nullptr; + __c.__begin_ = nullptr; + __c.__end_ = nullptr; + __c.__cap_ = nullptr; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) - : __end_cap_(nullptr), __alloc_(__a) { + : __cap_(nullptr), __alloc_(__a) { if (__a == __c.__alloc_) { - __first_ = __c.__first_; - __begin_ = __c.__begin_; - __end_ = __c.__end_; - __end_cap_ = __c.__end_cap_; - __c.__first_ = nullptr; - __c.__begin_ = nullptr; - __c.__end_ = nullptr; - __c.__end_cap_ = nullptr; + __first_ = __c.__first_; + __begin_ = __c.__begin_; + __end_ = __c.__end_; + __cap_ = __c.__cap_; + __c.__first_ = nullptr; + __c.__begin_ = nullptr; + __c.__end_ = nullptr; + __c.__cap_ = nullptr; } else { auto __allocation = std::__allocate_at_least(__alloc_, __c.size()); __first_ = __allocation.ptr; __begin_ = __end_ = __first_; - __end_cap_ = __first_ + __allocation.count; + __cap_ = __first_ + __allocation.count; typedef move_iterator _Ip; __construct_at_end(_Ip(__c.begin()), _Ip(__c.end())); } @@ -395,12 +384,12 @@ __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) !__alloc_traits::propagate_on_container_move_assignment::value) { clear(); shrink_to_fit(); - __first_ = __c.__first_; - __begin_ = __c.__begin_; - __end_ = __c.__end_; - __end_cap_ = __c.__end_cap_; + __first_ = __c.__first_; + __begin_ = __c.__begin_; + __end_ = __c.__end_; + __cap_ = __c.__cap_; __move_assign_alloc(__c, integral_constant()); - __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap_ = nullptr; + __c.__first_ = __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr; return *this; } @@ -410,22 +399,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split std::swap(__first_, __x.__first_); std::swap(__begin_, __x.__begin_); std::swap(__end_, __x.__end_); - std::swap(__end_cap_, __x.__end_cap_); + std::swap(__cap_, __x.__cap_); std::__swap_allocator(__alloc_, __x.__alloc_); } -template -_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::reserve(size_type __n) { - if (__n < capacity()) { - __split_buffer __t(__n, 0, __alloc_); - __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); - std::swap(__first_, __t.__first_); - std::swap(__begin_, __t.__begin_); - std::swap(__end_, __t.__end_); - std::swap(__end_cap_, __t.__end_cap_); - } -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT { if (capacity() > size()) { @@ -438,7 +415,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fi std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap_, __t.__end_cap_); + std::swap(__cap_, __t.__cap_); #if _LIBCPP_HAS_EXCEPTIONS } catch (...) { } @@ -450,19 +427,19 @@ template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_front(_Args&&... __args) { if (__begin_ == __first_) { - if (__end_ < __end_cap_) { - difference_type __d = __end_cap_ - __end_; + if (__end_ < __cap_) { + difference_type __d = __cap_ - __end_; __d = (__d + 1) / 2; __begin_ = std::move_backward(__begin_, __end_, __end_ + __d); __end_ += __d; } else { - size_type __c = std::max(2 * static_cast(__end_cap_ - __first_), 1); + size_type __c = std::max(2 * static_cast(__cap_ - __first_), 1); __split_buffer __t(__c, (__c + 3) / 4, __alloc_); __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap_, __t.__end_cap_); + std::swap(__cap_, __t.__cap_); } } __alloc_traits::construct(__alloc_, std::__to_address(__begin_ - 1), std::forward<_Args>(__args)...); @@ -472,20 +449,20 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_fron template template _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) { - if (__end_ == __end_cap_) { + if (__end_ == __cap_) { if (__begin_ > __first_) { difference_type __d = __begin_ - __first_; __d = (__d + 1) / 2; __end_ = std::move(__begin_, __end_, __begin_ - __d); __begin_ -= __d; } else { - size_type __c = std::max(2 * static_cast(__end_cap_ - __first_), 1); + size_type __c = std::max(2 * static_cast(__cap_ - __first_), 1); __split_buffer __t(__c, __c / 4, __alloc_); __t.__construct_at_end(move_iterator(__begin_), move_iterator(__end_)); std::swap(__first_, __t.__first_); std::swap(__begin_, __t.__begin_); std::swap(__end_, __t.__end_); - std::swap(__end_cap_, __t.__end_cap_); + std::swap(__cap_, __t.__cap_); } } __alloc_traits::construct(__alloc_, std::__to_address(__end_), std::forward<_Args>(__args)...); diff --git a/libcxx/include/__system_error/system_error.h b/libcxx/include/__system_error/system_error.h index 2763aaba88f5fa1bd2da40bd8021f5cf19e8625a..918effb6917cb4ac89c6fa549ad127dd50c9b18d 100644 --- a/libcxx/include/__system_error/system_error.h +++ b/libcxx/include/__system_error/system_error.h @@ -39,7 +39,6 @@ public: _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; } }; -[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void __throw_system_error(int __ev, const char* __what_arg); [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI inline void __throw_system_error(error_code __ec, const char* __what_arg) { #if _LIBCPP_HAS_EXCEPTIONS throw system_error(__ec, __what_arg); diff --git a/libcxx/include/__system_error/throw_system_error.h b/libcxx/include/__system_error/throw_system_error.h new file mode 100644 index 0000000000000000000000000000000000000000..e4605b6f014dc57fd4903347ea8eb6edd6145b44 --- /dev/null +++ b/libcxx/include/__system_error/throw_system_error.h @@ -0,0 +1,25 @@ +// -*- 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___SYSTEM_ERROR_THROW_SYSTEM_ERROR_H +#define _LIBCPP___SYSTEM_ERROR_THROW_SYSTEM_ERROR_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void __throw_system_error(int __ev, const char* __what_arg); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SYSTEM_ERROR_THROW_SYSTEM_ERROR_H diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h index f417abc07b87c58b37883aada8fb15bead72ac94..c40ffd25b903c2bae3be1564a041f66a6226fc38 100644 --- a/libcxx/include/__thread/thread.h +++ b/libcxx/include/__thread/thread.h @@ -18,10 +18,13 @@ #include <__functional/unary_function.h> #include <__memory/unique_ptr.h> #include <__mutex/mutex.h> -#include <__system_error/system_error.h> +#include <__system_error/throw_system_error.h> #include <__thread/id.h> #include <__thread/support.h> #include <__type_traits/decay.h> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_same.h> +#include <__type_traits/remove_cvref.h> #include <__utility/forward.h> #include diff --git a/libcxx/include/__type_traits/integral_constant.h b/libcxx/include/__type_traits/integral_constant.h index 23e87e27feff553a4c27136935a1bbedc5355970..b8c75c546aa9421c17942be0b7c2fe96113555a3 100644 --- a/libcxx/include/__type_traits/integral_constant.h +++ b/libcxx/include/__type_traits/integral_constant.h @@ -19,7 +19,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct _LIBCPP_TEMPLATE_VIS integral_constant { - static _LIBCPP_CONSTEXPR const _Tp value = __v; + static inline _LIBCPP_CONSTEXPR const _Tp value = __v; typedef _Tp value_type; typedef integral_constant type; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator value_type() const _NOEXCEPT { return value; } @@ -28,9 +28,6 @@ struct _LIBCPP_TEMPLATE_VIS integral_constant { #endif }; -template -_LIBCPP_CONSTEXPR const _Tp integral_constant<_Tp, __v>::value; - typedef integral_constant true_type; typedef integral_constant false_type; diff --git a/libcxx/include/__utility/scope_guard.h b/libcxx/include/__utility/scope_guard.h index 133e54212ed5920047985f6c178f88b6d34396f7..e51b300d1f50c7c6492f72340beac5b8e857e275 100644 --- a/libcxx/include/__utility/scope_guard.h +++ b/libcxx/include/__utility/scope_guard.h @@ -26,26 +26,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD template class __scope_guard { _Func __func_; - bool __moved_from_; public: - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __scope_guard(_Func __func) : __func_(std::move(__func)) {} + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __scope_guard(_Func __func) : __func_(std::move(__func)) {} _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__scope_guard() { __func_(); } - __scope_guard(const __scope_guard&) = delete; + __scope_guard(const __scope_guard&) = delete; + __scope_guard& operator=(const __scope_guard&) = delete; + __scope_guard& operator=(__scope_guard&&) = delete; -// C++17 has mandatory RVO, so we don't need the move constructor anymore to make __make_scope_guard work. +// C++14 doesn't have mandatory RVO, so we have to provide a declaration even though no compiler will ever generate +// a call to the move constructor. #if _LIBCPP_STD_VER <= 14 - __scope_guard(__scope_guard&& __other) : __func_(__other.__func_) { - _LIBCPP_ASSERT_INTERNAL(!__other.__moved_from_, "Cannot move twice from __scope_guard"); - __other.__moved_from_ = true; - } + __scope_guard(__scope_guard&&); #else __scope_guard(__scope_guard&&) = delete; #endif - - __scope_guard& operator=(const __scope_guard&) = delete; - __scope_guard& operator=(__scope_guard&&) = delete; }; template diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h index 6db202efb279b32032982dab167b0d539d4e63e8..ae3ea1de61de01dc579f050fed505aeeed1a4e07 100644 --- a/libcxx/include/__vector/vector.h +++ b/libcxx/include/__vector/vector.h @@ -11,7 +11,6 @@ #include <__algorithm/copy.h> #include <__algorithm/fill_n.h> -#include <__algorithm/iterator_operations.h> #include <__algorithm/max.h> #include <__algorithm/min.h> #include <__algorithm/move.h> @@ -22,6 +21,7 @@ #include <__debug_utils/sanitizers.h> #include <__format/enable_insertable.h> #include <__fwd/vector.h> +#include <__iterator/advance.h> #include <__iterator/bounded_iter.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> @@ -243,7 +243,7 @@ private: if (__vec_.__begin_ != nullptr) { __vec_.__clear(); __vec_.__annotate_delete(); - __alloc_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.capacity()); + __alloc_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.capacity()); } } @@ -255,7 +255,7 @@ public: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~vector() { __destroy_vector (*this)(); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(const vector& __x) - : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc())) { + : __alloc_(__alloc_traits::select_on_container_copy_construction(__x.__alloc_)) { __init_with_size(__x.__begin_, __x.__end_, __x.size()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI @@ -335,7 +335,7 @@ public: #endif _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { - return this->__alloc(); + return this->__alloc_; } // @@ -377,13 +377,13 @@ public: return static_cast(this->__end_ - this->__begin_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { - return static_cast(__end_cap() - this->__begin_); + return static_cast(this->__cap_ - this->__begin_); } [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return this->__begin_ == this->__end_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { - return std::min(__alloc_traits::max_size(this->__alloc()), numeric_limits::max()); + return std::min(__alloc_traits::max_size(this->__alloc_), numeric_limits::max()); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT; @@ -544,17 +544,17 @@ private: // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out - // Precondition: __begin_ == __end_ == __end_cap() == 0 + // Precondition: __begin_ == __end_ == __cap_ == nullptr // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); - auto __allocation = std::__allocate_at_least(__alloc(), __n); + auto __allocation = std::__allocate_at_least(this->__alloc_, __n); __begin_ = __allocation.ptr; __end_ = __allocation.ptr; - __end_cap() = __begin_ + __allocation.count; + __cap_ = __begin_ + __allocation.count; __annotate_new(0); } @@ -623,7 +623,7 @@ private: return std::__make_bounded_iter( std::__wrap_iter(__p), std::__wrap_iter(this->__begin_), - std::__wrap_iter(this->__end_cap())); + std::__wrap_iter(this->__cap_)); #else return iterator(__p); #endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR @@ -635,7 +635,7 @@ private: return std::__make_bounded_iter( std::__wrap_iter(__p), std::__wrap_iter(this->__begin_), - std::__wrap_iter(this->__end_cap())); + std::__wrap_iter(this->__cap_)); #else return const_iterator(__p); #endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR @@ -728,20 +728,10 @@ private: template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_one_at_end(_Args&&... __args) { _ConstructTransaction __tx(*this, 1); - __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...); + __alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...); ++__tx.__pos_; } - // TODO: Remove these now redundant accessors - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return this->__alloc_; } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { - return this->__alloc_; - } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return this->__cap_; } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT { - return this->__cap_; - } - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __clear() _NOEXCEPT { __base_destruct_at_end(this->__begin_); } @@ -749,7 +739,7 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT { pointer __soon_to_be_end = this->__end_; while (__new_last != __soon_to_be_end) - __alloc_traits::destroy(__alloc(), std::__to_address(--__soon_to_be_end)); + __alloc_traits::destroy(this->__alloc_, std::__to_address(--__soon_to_be_end)); this->__end_ = __new_last; } @@ -763,25 +753,25 @@ private: __move_assign_alloc(__c, integral_constant()); } - [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("vector"); } + [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_length_error() { std::__throw_length_error("vector"); } - [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("vector"); } + [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector& __c, true_type) { - if (__alloc() != __c.__alloc()) { + if (this->__alloc_ != __c.__alloc_) { __clear(); __annotate_delete(); - __alloc_traits::deallocate(__alloc(), this->__begin_, capacity()); - this->__begin_ = this->__end_ = __end_cap() = nullptr; + __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity()); + this->__begin_ = this->__end_ = this->__cap_ = nullptr; } - __alloc() = __c.__alloc(); + this->__alloc_ = __c.__alloc_; } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const vector&, false_type) {} _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { - __alloc() = std::move(__c.__alloc()); + this->__alloc_ = std::move(__c.__alloc_); } _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} @@ -817,12 +807,12 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer__alloc_, std::__to_address(__begin_), std::__to_address(__end_), std::__to_address(__new_begin)); __v.__begin_ = __new_begin; __end_ = __begin_; // All the objects have been destroyed by relocating them. std::swap(this->__begin_, __v.__begin_); std::swap(this->__end_, __v.__end_); - std::swap(this->__end_cap(), __v.__end_cap_); + std::swap(this->__cap_, __v.__cap_); __v.__first_ = __v.__begin_; __annotate_new(size()); } @@ -840,19 +830,19 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer__alloc_, std::__to_address(__p), std::__to_address(__end_), std::__to_address(__v.__end_)); __v.__end_ += (__end_ - __p); __end_ = __p; // The objects in [__p, __end_) have been destroyed by relocating them. auto __new_begin = __v.__begin_ - (__p - __begin_); std::__uninitialized_allocator_relocate( - __alloc(), std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin)); + this->__alloc_, std::__to_address(__begin_), std::__to_address(__p), std::__to_address(__new_begin)); __v.__begin_ = __new_begin; __end_ = __begin_; // All the objects have been destroyed by relocating them. std::swap(this->__begin_, __v.__begin_); std::swap(this->__end_, __v.__end_); - std::swap(this->__end_cap(), __v.__end_cap_); + std::swap(this->__cap_, __v.__cap_); __v.__first_ = __v.__begin_; __annotate_new(size()); return __ret; @@ -863,8 +853,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__vdeallocate() _NOE if (this->__begin_ != nullptr) { clear(); __annotate_delete(); - __alloc_traits::deallocate(this->__alloc(), this->__begin_, capacity()); - this->__begin_ = this->__end_ = this->__end_cap() = nullptr; + __alloc_traits::deallocate(this->__alloc_, this->__begin_, capacity()); + this->__begin_ = this->__end_ = this->__cap_ = nullptr; } } @@ -891,7 +881,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s _ConstructTransaction __tx(*this, __n); const_pointer __new_end = __tx.__new_end_; for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) { - __alloc_traits::construct(this->__alloc(), std::__to_address(__pos)); + __alloc_traits::construct(this->__alloc_, std::__to_address(__pos)); } } @@ -907,7 +897,7 @@ vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) _ConstructTransaction __tx(*this, __n); const_pointer __new_end = __tx.__new_end_; for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) { - __alloc_traits::construct(this->__alloc(), std::__to_address(__pos), __x); + __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), __x); } } @@ -916,7 +906,7 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) { _ConstructTransaction __tx(*this, __n); - __tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_); + __tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, __first, __last, __tx.__pos_); } // Default constructs __n objects starting at __end_ @@ -925,11 +915,10 @@ vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __ // Exception safety: strong. template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type __n) { - if (static_cast(this->__end_cap() - this->__end_) >= __n) + if (static_cast(this->__cap_ - this->__end_) >= __n) this->__construct_at_end(__n); else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + __n), size(), __a); + __split_buffer __v(__recommend(size() + __n), size(), this->__alloc_); __v.__construct_at_end(__n); __swap_out_circular_buffer(__v); } @@ -941,11 +930,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type _ // Exception safety: strong. template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__append(size_type __n, const_reference __x) { - if (static_cast(this->__end_cap() - this->__end_) >= __n) + if (static_cast(this->__cap_ - this->__end_) >= __n) this->__construct_at_end(__n, __x); else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + __n), size(), __a); + __split_buffer __v(__recommend(size() + __n), size(), this->__alloc_); __v.__construct_at_end(__n, __x); __swap_out_circular_buffer(__v); } @@ -958,22 +946,22 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocato #else _NOEXCEPT_(is_nothrow_move_constructible::value) #endif - : __alloc_(std::move(__x.__alloc())) { - this->__begin_ = __x.__begin_; - this->__end_ = __x.__end_; - this->__end_cap() = __x.__end_cap(); - __x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr; + : __alloc_(std::move(__x.__alloc_)) { + this->__begin_ = __x.__begin_; + this->__end_ = __x.__end_; + this->__cap_ = __x.__cap_; + __x.__begin_ = __x.__end_ = __x.__cap_ = nullptr; } template _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t& __a) : __alloc_(__a) { - if (__a == __x.__alloc()) { - this->__begin_ = __x.__begin_; - this->__end_ = __x.__end_; - this->__end_cap() = __x.__end_cap(); - __x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr; + if (__a == __x.__alloc_) { + this->__begin_ = __x.__begin_; + this->__end_ = __x.__end_; + this->__cap_ = __x.__cap_; + __x.__begin_ = __x.__end_ = __x.__cap_ = nullptr; } else { typedef move_iterator _Ip; auto __guard = std::__make_exception_guard(__destroy_vector(*this)); @@ -985,7 +973,7 @@ vector<_Tp, _Allocator>::vector(vector&& __x, const __type_identity_t _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type) _NOEXCEPT_(__alloc_traits::is_always_equal::value) { - if (__alloc() != __c.__alloc()) { + if (this->__alloc_ != __c.__alloc_) { typedef move_iterator _Ip; assign(_Ip(__c.begin()), _Ip(__c.end())); } else @@ -997,10 +985,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__move_assign(vector _NOEXCEPT_(is_nothrow_move_assignable::value) { __vdeallocate(); __move_assign_alloc(__c); // this can throw - this->__begin_ = __c.__begin_; - this->__end_ = __c.__end_; - this->__end_cap() = __c.__end_cap(); - __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; + this->__begin_ = __c.__begin_; + this->__end_ = __c.__end_; + this->__cap_ = __c.__cap_; + __c.__begin_ = __c.__end_ = __c.__cap_ = nullptr; } template @@ -1033,7 +1021,7 @@ vector<_Tp, _Allocator>::__assign_with_size(_ForwardIterator __first, _Sentinel std::copy(__first, __mid, this->__begin_); __construct_at_end(__mid, __last, __new_size - size()); } else { - pointer __m = std::__copy<_ClassicAlgPolicy>(__first, __last, this->__begin_).second; + pointer __m = std::__copy(__first, __last, this->__begin_).second; this->__destruct_at_end(__m); } } else { @@ -1064,8 +1052,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::reserve(size_type __ if (__n > capacity()) { if (__n > max_size()) this->__throw_length_error(); - allocator_type& __a = this->__alloc(); - __split_buffer __v(__n, size(), __a); + __split_buffer __v(__n, size(), this->__alloc_); __swap_out_circular_buffer(__v); } } @@ -1076,8 +1063,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::shrink_to_fit() _NOE #if _LIBCPP_HAS_EXCEPTIONS try { #endif // _LIBCPP_HAS_EXCEPTIONS - allocator_type& __a = this->__alloc(); - __split_buffer __v(size(), size(), __a); + __split_buffer __v(size(), size(), this->__alloc_); // The Standard mandates shrink_to_fit() does not increase the capacity. // With equal capacity keep the existing buffer. This avoids extra work // due to swapping the elements. @@ -1094,10 +1080,9 @@ template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args) { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + 1), size(), __a); + __split_buffer __v(__recommend(size() + 1), size(), this->__alloc_); // __v.emplace_back(std::forward<_Args>(__args)...); - __alloc_traits::construct(__a, std::__to_address(__v.__end_), std::forward<_Args>(__args)...); + __alloc_traits::construct(this->__alloc_, std::__to_address(__v.__end_), std::forward<_Args>(__args)...); __v.__end_++; __swap_out_circular_buffer(__v); return this->__end_; @@ -1113,7 +1098,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline #endif vector<_Tp, _Allocator>::emplace_back(_Args&&... __args) { pointer __end = this->__end_; - if (__end < this->__end_cap()) { + if (__end < this->__cap_) { __construct_one_at_end(std::forward<_Args>(__args)...); ++__end; } else { @@ -1156,7 +1141,7 @@ vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointe pointer __i = __from_s + __n; _ConstructTransaction __tx(*this, __from_e - __i); for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) { - __alloc_traits::construct(this->__alloc(), std::__to_address(__pos), std::move(*__i)); + __alloc_traits::construct(this->__alloc_, std::__to_address(__pos), std::move(*__i)); } } std::move_backward(__from_s, __from_s + __n, __old_last); @@ -1166,7 +1151,7 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) { pointer __p = this->__begin_ + (__position - begin()); - if (this->__end_ < this->__end_cap()) { + if (this->__end_ < this->__cap_) { if (__p == this->__end_) { __construct_one_at_end(__x); } else { @@ -1177,8 +1162,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x) *__p = *__xr; } } else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); + __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_); __v.emplace_back(__x); __p = __swap_out_circular_buffer(__v, __p); } @@ -1189,7 +1173,7 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { pointer __p = this->__begin_ + (__position - begin()); - if (this->__end_ < this->__end_cap()) { + if (this->__end_ < this->__cap_) { if (__p == this->__end_) { __construct_one_at_end(std::move(__x)); } else { @@ -1197,8 +1181,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x) { *__p = std::move(__x); } } else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); + __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_); __v.emplace_back(std::move(__x)); __p = __swap_out_circular_buffer(__v, __p); } @@ -1210,17 +1193,16 @@ template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args) { pointer __p = this->__begin_ + (__position - begin()); - if (this->__end_ < this->__end_cap()) { + if (this->__end_ < this->__cap_) { if (__p == this->__end_) { __construct_one_at_end(std::forward<_Args>(__args)...); } else { - __temp_value __tmp(this->__alloc(), std::forward<_Args>(__args)...); + __temp_value __tmp(this->__alloc_, std::forward<_Args>(__args)...); __move_range(__p, this->__end_, __p + 1); *__p = std::move(__tmp.get()); } } else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, __a); + __split_buffer __v(__recommend(size() + 1), __p - this->__begin_, this->__alloc_); __v.emplace_back(std::forward<_Args>(__args)...); __p = __swap_out_circular_buffer(__v, __p); } @@ -1233,7 +1215,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { // We can't compare unrelated pointers inside constant expressions - if (!__libcpp_is_constant_evaluated() && __n <= static_cast(this->__end_cap() - this->__end_)) { + if (!__libcpp_is_constant_evaluated() && __n <= static_cast(this->__cap_ - this->__end_)) { size_type __old_n = __n; pointer __old_last = this->__end_; if (__n > static_cast(this->__end_ - __p)) { @@ -1249,8 +1231,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_ std::fill_n(__p, __n, *__xr); } } else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, __a); + __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_); __v.__construct_at_end(__n, __x); __p = __swap_out_circular_buffer(__v, __p); } @@ -1264,12 +1245,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Alloca vector<_Tp, _Allocator>::__insert_with_sentinel(const_iterator __position, _InputIterator __first, _Sentinel __last) { difference_type __off = __position - begin(); pointer __p = this->__begin_ + __off; - allocator_type& __a = this->__alloc(); pointer __old_last = this->__end_; - for (; this->__end_ != this->__end_cap() && __first != __last; ++__first) { + for (; this->__end_ != this->__cap_ && __first != __last; ++__first) { __construct_one_at_end(*__first); } - __split_buffer __v(__a); + __split_buffer __v(this->__alloc_); if (__first != __last) { #if _LIBCPP_HAS_EXCEPTIONS try { @@ -1300,7 +1280,7 @@ vector<_Tp, _Allocator>::__insert_with_size( auto __insertion_size = __n; pointer __p = this->__begin_ + (__position - begin()); if (__n > 0) { - if (__n <= this->__end_cap() - this->__end_) { + if (__n <= this->__cap_ - this->__end_) { size_type __old_n = __n; pointer __old_last = this->__end_; _Iterator __m = std::next(__first, __n); @@ -1317,8 +1297,7 @@ vector<_Tp, _Allocator>::__insert_with_size( std::copy(__first, __m, __p); } } else { - allocator_type& __a = this->__alloc(); - __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, __a); + __split_buffer __v(__recommend(size() + __n), __p - this->__begin_, this->__alloc_); __v.__construct_at_end_with_size(__first, __insertion_size); __p = __swap_out_circular_buffer(__v, __p); } @@ -1353,26 +1332,26 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::swap(vector& __x) #endif { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( - __alloc_traits::propagate_on_container_swap::value || this->__alloc() == __x.__alloc(), + __alloc_traits::propagate_on_container_swap::value || this->__alloc_ == __x.__alloc_, "vector::swap: Either propagate_on_container_swap must be true" " or the allocators must compare equal"); std::swap(this->__begin_, __x.__begin_); std::swap(this->__end_, __x.__end_); - std::swap(this->__end_cap(), __x.__end_cap()); - std::__swap_allocator(this->__alloc(), __x.__alloc()); + std::swap(this->__cap_, __x.__cap_); + std::__swap_allocator(this->__alloc_, __x.__alloc_); } template _LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector<_Tp, _Allocator>::__invariants() const { if (this->__begin_ == nullptr) { - if (this->__end_ != nullptr || this->__end_cap() != nullptr) + if (this->__end_ != nullptr || this->__cap_ != nullptr) return false; } else { if (this->__begin_ > this->__end_) return false; - if (this->__begin_ == this->__end_cap()) + if (this->__begin_ == this->__cap_) return false; - if (this->__end_ > this->__end_cap()) + if (this->__end_ > this->__cap_) return false; } return true; diff --git a/libcxx/include/__vector/vector_bool.h b/libcxx/include/__vector/vector_bool.h index 462095fd07acf7189fb2edb5654159920f198397..3b03f65b7ee5498b0e0b3e49c318e3cefabe8df6 100644 --- a/libcxx/include/__vector/vector_bool.h +++ b/libcxx/include/__vector/vector_bool.h @@ -107,14 +107,6 @@ public: #endif private: - // TODO: Remove these now redundant accessors - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type& __cap() _NOEXCEPT { return __cap_; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const size_type& __cap() const _NOEXCEPT { return __cap_; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __storage_allocator& __alloc() _NOEXCEPT { return __alloc_; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const __storage_allocator& __alloc() const _NOEXCEPT { - return __alloc_; - } - static const unsigned __bits_per_word = static_cast(sizeof(__storage_type) * CHAR_BIT); _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type @@ -144,7 +136,7 @@ private: _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void operator()() { if (__vec_.__begin_ != nullptr) - __storage_traits::deallocate(__vec_.__alloc(), __vec_.__begin_, __vec_.__cap()); + __storage_traits::deallocate(__vec_.__alloc_, __vec_.__begin_, __vec_.__cap_); } private: @@ -240,12 +232,12 @@ public: #endif _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 allocator_type get_allocator() const _NOEXCEPT { - return allocator_type(this->__alloc()); + return allocator_type(this->__alloc_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type capacity() const _NOEXCEPT { - return __internal_cap_to_external(__cap()); + return __internal_cap_to_external(__cap_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type size() const _NOEXCEPT { return __size_; } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool empty() const _NOEXCEPT { @@ -378,9 +370,9 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __invariants() const; private: - [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { std::__throw_length_error("vector"); } + [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_length_error() { std::__throw_length_error("vector"); } - [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("vector"); } + [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("vector"); } template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void @@ -406,7 +398,7 @@ private: #if _LIBCPP_HAS_EXCEPTIONS } catch (...) { if (__begin_ != nullptr) - __storage_traits::deallocate(__alloc(), __begin_, __cap()); + __storage_traits::deallocate(__alloc_, __begin_, __cap_); throw; } #endif // _LIBCPP_HAS_EXCEPTIONS @@ -430,19 +422,19 @@ private: // Allocate space for __n objects // throws length_error if __n > max_size() // throws (probably bad_alloc) if memory run out - // Precondition: __begin_ == __end_ == __cap() == 0 + // Precondition: __begin_ == __end_ == __cap_ == nullptr // Precondition: __n > 0 // Postcondition: capacity() >= __n // Postcondition: size() == 0 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __vallocate(size_type __n) { if (__n > max_size()) __throw_length_error(); - auto __allocation = std::__allocate_at_least(__alloc(), __external_cap_to_internal(__n)); + auto __allocation = std::__allocate_at_least(__alloc_, __external_cap_to_internal(__n)); __begin_ = __allocation.ptr; __size_ = 0; - __cap() = __allocation.count; + __cap_ = __allocation.count; if (__libcpp_is_constant_evaluated()) { - for (size_type __i = 0; __i != __cap(); ++__i) + for (size_type __i = 0; __i != __cap_; ++__i) std::__construct_at(std::__to_address(__begin_) + __i); } } @@ -479,9 +471,9 @@ private: __v, integral_constant()); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector& __c, true_type) { - if (__alloc() != __c.__alloc()) + if (__alloc_ != __c.__alloc_) __vdeallocate(); - __alloc() = __c.__alloc(); + __alloc_ = __c.__alloc_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __copy_assign_alloc(const vector&, false_type) {} @@ -497,7 +489,7 @@ private: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable::value) { - __alloc() = std::move(__c.__alloc()); + __alloc_ = std::move(__c.__alloc_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(vector&, false_type) _NOEXCEPT {} @@ -515,16 +507,16 @@ private: template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__vdeallocate() _NOEXCEPT { if (this->__begin_ != nullptr) { - __storage_traits::deallocate(this->__alloc(), this->__begin_, __cap()); + __storage_traits::deallocate(this->__alloc_, this->__begin_, __cap_); this->__begin_ = nullptr; - this->__size_ = this->__cap() = 0; + this->__size_ = this->__cap_ = 0; } } template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector::size_type vector::max_size() const _NOEXCEPT { - size_type __amax = __storage_traits::max_size(__alloc()); + size_type __amax = __storage_traits::max_size(__alloc_); size_type __nmax = numeric_limits::max() / 2; // end() >= begin(), always if (__nmax / __bits_per_word <= __amax) return __nmax; @@ -574,7 +566,7 @@ vector::__construct_at_end(_InputIterator __first, _Sentinel _ else this->__begin_[(this->__size_ - 1) / __bits_per_word] = __storage_type(0); } - std::__copy<_ClassicAlgPolicy>(__first, __last, __make_iter(__old_size)); + std::__copy(__first, __last, __make_iter(__old_size)); } template @@ -693,7 +685,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(const vector& __v : __begin_(nullptr), __size_(0), __cap_(0), - __alloc_(__storage_traits::select_on_container_copy_construction(__v.__alloc())) { + __alloc_(__storage_traits::select_on_container_copy_construction(__v.__alloc_)) { if (__v.size() > 0) { __vallocate(__v.size()); __construct_at_end(__v.begin(), __v.end(), __v.size()); @@ -738,19 +730,19 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 vector _LIBCPP_CONSTEXPR_SINCE_CXX20 vector::vector(vector&& __v, const __type_identity_t& __a) : __begin_(nullptr), __size_(0), __cap_(0), __alloc_(__a) { - if (__a == allocator_type(__v.__alloc())) { + if (__a == allocator_type(__v.__alloc_)) { this->__begin_ = __v.__begin_; this->__size_ = __v.__size_; - this->__cap() = __v.__cap(); + this->__cap_ = __v.__cap_; __v.__begin_ = nullptr; - __v.__cap() = __v.__size_ = 0; + __v.__cap_ = __v.__size_ = 0; } else if (__v.size() > 0) { __vallocate(__v.size()); __construct_at_end(__v.begin(), __v.end(), __v.size()); @@ -767,7 +759,7 @@ vector::operator=(vector&& __v) template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__move_assign(vector& __c, false_type) { - if (__alloc() != __c.__alloc()) + if (__alloc_ != __c.__alloc_) assign(__c.begin(), __c.end()); else __move_assign(__c, true_type()); @@ -780,9 +772,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::__move_assign(vecto __move_assign_alloc(__c); this->__begin_ = __c.__begin_; this->__size_ = __c.__size_; - this->__cap() = __c.__cap(); + this->__cap_ = __c.__cap_; __c.__begin_ = nullptr; - __c.__cap() = __c.__size_ = 0; + __c.__cap_ = __c.__size_ = 0; } template @@ -855,11 +847,11 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::reserve(size_type _ template _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::shrink_to_fit() _NOEXCEPT { - if (__external_cap_to_internal(size()) > __cap()) { + if (__external_cap_to_internal(size()) > __cap_) { #if _LIBCPP_HAS_EXCEPTIONS try { #endif // _LIBCPP_HAS_EXCEPTIONS - vector(*this, allocator_type(__alloc())).swap(*this); + vector(*this, allocator_type(__alloc_)).swap(*this); #if _LIBCPP_HAS_EXCEPTIONS } catch (...) { } @@ -1002,7 +994,7 @@ vector::__insert_with_size( std::copy_backward(__position, cend(), __v.end()); swap(__v); } - std::__copy<_ClassicAlgPolicy>(__first, __last, __r); + std::__copy(__first, __last, __r); return __r; } @@ -1035,8 +1027,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::swap(vector& __x) { std::swap(this->__begin_, __x.__begin_); std::swap(this->__size_, __x.__size_); - std::swap(this->__cap(), __x.__cap()); - std::__swap_allocator(this->__alloc(), __x.__alloc()); + std::swap(this->__cap_, __x.__cap_); + std::__swap_allocator(this->__alloc_, __x.__alloc_); } template @@ -1080,10 +1072,10 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector::flip() _NOEXCEPT { template _LIBCPP_CONSTEXPR_SINCE_CXX20 bool vector::__invariants() const { if (this->__begin_ == nullptr) { - if (this->__size_ != 0 || this->__cap() != 0) + if (this->__size_ != 0 || this->__cap_ != 0) return false; } else { - if (this->__cap() == 0) + if (this->__cap_ == 0) return false; if (this->__size_ > this->capacity()) return false; diff --git a/libcxx/include/any b/libcxx/include/any index 719dc2cf999e5055254e43748ee079dabca6167a..cae56fa376e057e07557551bbed9819a934a530d 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -166,8 +166,6 @@ template struct _LIBCPP_TEMPLATE_VIS __unique_typeinfo { static constexpr int __id = 0; }; -template -constexpr int __unique_typeinfo<_Tp>::__id; template inline _LIBCPP_HIDE_FROM_ABI constexpr const void* __get_fallback_typeid() { diff --git a/libcxx/include/atomic b/libcxx/include/atomic index 716d198bc236bbcce3f60e884469adac4b418f3f..d4adf277c49c7a61e363472d90377a2197496865 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -591,7 +591,6 @@ template #include <__atomic/aliases.h> #include <__atomic/atomic.h> -#include <__atomic/atomic_base.h> #include <__atomic/atomic_flag.h> #include <__atomic/atomic_init.h> #include <__atomic/atomic_lock_free.h> diff --git a/libcxx/include/barrier b/libcxx/include/barrier index c7df0e9e6e8d43f28a9e2aaa87cb9f9b903beb9d..980eae06ab140f62cf429d759039d6217f3a98b3 100644 --- a/libcxx/include/barrier +++ b/libcxx/include/barrier @@ -50,7 +50,7 @@ namespace std #if _LIBCPP_HAS_THREADS # include <__assert> -# include <__atomic/atomic_base.h> +# include <__atomic/atomic.h> # include <__atomic/memory_order.h> # include <__cstddef/ptrdiff_t.h> # include <__memory/unique_ptr.h> @@ -109,9 +109,9 @@ template class __barrier_base { ptrdiff_t __expected_; unique_ptr<__barrier_algorithm_base, void (*)(__barrier_algorithm_base*)> __base_; - __atomic_base __expected_adjustment_; + atomic __expected_adjustment_; _CompletionF __completion_; - __atomic_base<__barrier_phase_t> __phase_; + atomic<__barrier_phase_t> __phase_; public: using arrival_token = __barrier_phase_t; @@ -167,10 +167,10 @@ Two versions of this algorithm are provided: template class __barrier_base { - __atomic_base __expected; - __atomic_base __arrived; + atomic __expected; + atomic __arrived; _CompletionF __completion; - __atomic_base __phase; + atomic __phase; public: using arrival_token = bool; @@ -212,7 +212,7 @@ class __barrier_base<__empty_completion> { static constexpr uint64_t __phase_bit = 1ull << 63; static constexpr uint64_t __arrived_mask = (__phase_bit - 1) & ~__expected_mask; - __atomic_base __phase_arrived_expected; + atomic __phase_arrived_expected; static _LIBCPP_HIDE_FROM_ABI constexpr uint64_t __init(ptrdiff_t __count) _NOEXCEPT { return ((uint64_t(1u << 31) - __count) << 32) | (uint64_t(1u << 31) - __count); diff --git a/libcxx/include/bit b/libcxx/include/bit index 94387d101a398f0793e11dc7004b7529a7c00a9b..092aebca26a31ddbf0769fe853c54ac536a8dac5 100644 --- a/libcxx/include/bit +++ b/libcxx/include/bit @@ -87,10 +87,6 @@ namespace std { # pragma GCC system_header #endif -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 -# include -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include diff --git a/libcxx/include/charconv b/libcxx/include/charconv index 8f5e697eec439654ccbc41e93757bcf71a876cd4..a65b3d35270803e9f020cb34d9233afaa2b7bed2 100644 --- a/libcxx/include/charconv +++ b/libcxx/include/charconv @@ -101,13 +101,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 14 -# include -# include -# include -# include -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include diff --git a/libcxx/include/compare b/libcxx/include/compare index de0e4c7ec2280c430dd73678995d686c6ea41000..440d4c4b4dd26d1ddf7cbd2fc58b0e11d628a078 100644 --- a/libcxx/include/compare +++ b/libcxx/include/compare @@ -164,12 +164,6 @@ namespace std { # pragma GCC system_header #endif -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 -# include -# include -# include -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include diff --git a/libcxx/include/deque b/libcxx/include/deque index 55d0bf9311bbb74488b90193da1a016e776cd8e7..ad66750348974137f63dbfc2005e94109910298b 100644 --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -2073,7 +2073,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity() { std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap_, __buf.__end_cap_); + std::swap(__map_.__cap_, __buf.__cap_); __start_ = __map_.size() == 1 ? __block_size / 2 : __start_ + __block_size; } __annotate_whole_block(0, __asan_poison); @@ -2150,7 +2150,7 @@ void deque<_Tp, _Allocator>::__add_front_capacity(size_type __n) { std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap_, __buf.__end_cap_); + std::swap(__map_.__cap_, __buf.__cap_); __start_ += __ds; } } @@ -2196,7 +2196,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity() { std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap_, __buf.__end_cap_); + std::swap(__map_.__cap_, __buf.__cap_); __annotate_whole_block(__map_.size() - 1, __asan_poison); } } @@ -2275,7 +2275,7 @@ void deque<_Tp, _Allocator>::__add_back_capacity(size_type __n) { std::swap(__map_.__first_, __buf.__first_); std::swap(__map_.__begin_, __buf.__begin_); std::swap(__map_.__end_, __buf.__end_); - std::swap(__map_.__end_cap_, __buf.__end_cap_); + std::swap(__map_.__cap_, __buf.__cap_); __start_ -= __ds; } } diff --git a/libcxx/include/expected b/libcxx/include/expected index 6a2f12f2bf3b5d44cdb2ed572fdb786a32826222..3c7ef336432a10e059aa241377690f80f3084fda 100644 --- a/libcxx/include/expected +++ b/libcxx/include/expected @@ -53,10 +53,4 @@ namespace std { # pragma GCC system_header #endif -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 -# include -# include -# include -#endif - #endif // _LIBCPP_EXPECTED diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index a511fef31bc5d159595cd9a3ca2625dbe85683cb..57730870ddf43ed4f250464cba333ebaeb0f4e38 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -503,9 +503,6 @@ protected: return pointer_traits<__begin_node_pointer>::pointer_to(const_cast<__begin_node&>(__before_begin_)); } - _LIBCPP_HIDE_FROM_ABI __node_allocator& __alloc() _NOEXCEPT { return __alloc_; } - _LIBCPP_HIDE_FROM_ABI const __node_allocator& __alloc() const _NOEXCEPT { return __alloc_; } - typedef __forward_list_iterator<__node_pointer> iterator; typedef __forward_list_const_iterator<__node_pointer> const_iterator; @@ -541,8 +538,7 @@ protected: template _LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__node_pointer __next, _Args&&... __args) { - __node_allocator& __a = __alloc(); - __allocation_guard<__node_allocator> __guard(__a, 1); + __allocation_guard<__node_allocator> __guard(__alloc_, 1); // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value // held inside the node, since we need to use the allocator's construct() method for that. // @@ -552,17 +548,16 @@ protected: std::__construct_at(std::addressof(*__guard.__get()), __next); // Now construct the value_type using the allocator's construct() method. - __node_traits::construct(__a, std::addressof(__guard.__get()->__get_value()), std::forward<_Args>(__args)...); + __node_traits::construct(__alloc_, std::addressof(__guard.__get()->__get_value()), std::forward<_Args>(__args)...); return __guard.__release_ptr(); } _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) { // For the same reason as above, we use the allocator's destroy() method for the value_type, // but not for the node itself. - __node_allocator& __a = __alloc(); - __node_traits::destroy(__a, std::addressof(__node->__get_value())); + __node_traits::destroy(__alloc_, std::addressof(__node->__get_value())); std::__destroy_at(std::addressof(*__node)); - __node_traits::deallocate(__a, __node, 1); + __node_traits::deallocate(__alloc_, __node, 1); } public: @@ -579,15 +574,15 @@ protected: private: _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base&, false_type) {} _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base& __x, true_type) { - if (__alloc() != __x.__alloc()) + if (__alloc_ != __x.__alloc_) clear(); - __alloc() = __x.__alloc(); + __alloc_ = __x.__alloc_; } _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base&, false_type) _NOEXCEPT {} _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { - __alloc() = std::move(__x.__alloc()); + __alloc_ = std::move(__x.__alloc_); } }; @@ -603,7 +598,7 @@ inline __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base template inline __forward_list_base<_Tp, _Alloc>::__forward_list_base(__forward_list_base&& __x, const allocator_type& __a) : __before_begin_(__begin_node()), __alloc_(__node_allocator(__a)) { - if (__alloc() == __x.__alloc()) { + if (__alloc_ == __x.__alloc_) { __before_begin()->__next_ = __x.__before_begin()->__next_; __x.__before_begin()->__next_ = nullptr; } @@ -624,7 +619,7 @@ inline void __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x) _NOEXCEPT_(!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>) #endif { - std::__swap_allocator(__alloc(), __x.__alloc()); + std::__swap_allocator(__alloc_, __x.__alloc_); using std::swap; swap(__before_begin()->__next_, __x.__before_begin()->__next_); } @@ -739,7 +734,7 @@ public: _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const value_type& __v); - _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(__base::__alloc()); } + _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT { return allocator_type(this->__alloc_); } _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__base::__before_begin()->__next_); } _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { @@ -765,7 +760,7 @@ public: return __base::__before_begin()->__next_ == nullptr; } _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { - return std::min(__node_traits::max_size(__base::__alloc()), numeric_limits::max()); + return std::min(__node_traits::max_size(this->__alloc_), numeric_limits::max()); } _LIBCPP_HIDE_FROM_ABI reference front() { return __base::__before_begin()->__next_->__get_value(); } @@ -944,7 +939,7 @@ forward_list<_Tp, _Alloc>::forward_list(_InputIterator __f, _InputIterator __l, template forward_list<_Tp, _Alloc>::forward_list(const forward_list& __x) - : __base(__node_traits::select_on_container_copy_construction(__x.__alloc())) { + : __base(__node_traits::select_on_container_copy_construction(__x.__alloc_)) { insert_after(cbefore_begin(), __x.begin(), __x.end()); } @@ -967,7 +962,7 @@ forward_list<_Tp, _Alloc>& forward_list<_Tp, _Alloc>::operator=(const forward_li template forward_list<_Tp, _Alloc>::forward_list(forward_list&& __x, const __type_identity_t& __a) : __base(std::move(__x), __a) { - if (__base::__alloc() != __x.__alloc()) { + if (this->__alloc_ != __x.__alloc_) { typedef move_iterator _Ip; insert_after(cbefore_begin(), _Ip(__x.begin()), _Ip(__x.end())); } @@ -994,7 +989,7 @@ void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, true_type) template void forward_list<_Tp, _Alloc>::__move_assign(forward_list& __x, false_type) { - if (__base::__alloc() == __x.__alloc()) + if (this->__alloc_ == __x.__alloc_) __move_assign(__x, true_type()); else { typedef move_iterator _Ip; diff --git a/libcxx/include/fstream b/libcxx/include/fstream index e3b9abbbdcf056c6b846579f0bee96437603aa1a..e188bfc9042a7c9afbf2513adcaeb0ae542d26cb 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -193,6 +193,8 @@ typedef basic_fstream wfstream; #include <__fwd/fstream.h> #include <__locale> #include <__memory/addressof.h> +#include <__memory/unique_ptr.h> +#include <__ostream/basic_ostream.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_same.h> #include <__utility/move.h> @@ -200,7 +202,7 @@ typedef basic_fstream wfstream; #include <__utility/unreachable.h> #include #include -#include +#include #include #include diff --git a/libcxx/include/future b/libcxx/include/future index 67d9b43ff22e3238de168fa122202eff81ba0de4..cbf3ed93464176e48df6b95a28ffbd9e97214a14 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -378,12 +378,13 @@ template struct uses_allocator, Alloc>; # include <__memory/allocator_traits.h> # include <__memory/compressed_pair.h> # include <__memory/pointer_traits.h> -# include <__memory/shared_ptr.h> +# include <__memory/shared_count.h> # include <__memory/unique_ptr.h> # include <__memory/uses_allocator.h> # include <__system_error/error_category.h> # include <__system_error/error_code.h> # include <__system_error/error_condition.h> +# include <__thread/thread.h> # include <__type_traits/add_lvalue_reference.h> # include <__type_traits/aligned_storage.h> # include <__type_traits/conditional.h> @@ -397,7 +398,6 @@ template struct uses_allocator, Alloc>; # include # include # include -# include # include # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -2071,6 +2071,7 @@ _LIBCPP_POP_MACROS # include # include # include +# include #endif #endif // _LIBCPP_FUTURE diff --git a/libcxx/include/iomanip b/libcxx/include/iomanip index 8c711c94f117624f6408786d07d0da96f3ea4d2d..6118f8fb5b417b7b4e04c9557ac4ef0aae95da97 100644 --- a/libcxx/include/iomanip +++ b/libcxx/include/iomanip @@ -46,9 +46,9 @@ template #if _LIBCPP_HAS_LOCALIZATION -# include <__ostream/basic_ostream.h> +# include <__ostream/put_character_sequence.h> # include -# include +# include # include # include @@ -547,4 +547,19 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_HAS_LOCALIZATION +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + #endif // _LIBCPP_IOMANIP diff --git a/libcxx/include/latch b/libcxx/include/latch index 90cca27c50c3762b2264612b37f465e62d5abe3d..1860ed816c856201ab90217051989d7470ed1bf5 100644 --- a/libcxx/include/latch +++ b/libcxx/include/latch @@ -45,7 +45,7 @@ namespace std #if _LIBCPP_HAS_THREADS # include <__assert> -# include <__atomic/atomic_base.h> +# include <__atomic/atomic.h> # include <__atomic/atomic_sync.h> # include <__atomic/memory_order.h> # include <__cstddef/ptrdiff_t.h> @@ -64,7 +64,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD class latch { - __atomic_base __a_; + atomic __a_; public: static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return numeric_limits::max(); } diff --git a/libcxx/include/limits b/libcxx/include/limits index b85c66257d27b7bd11260bb311d3194735c3fcbb..da0a92d7daff4a7f0d27041e63960f002976ed25 100644 --- a/libcxx/include/limits +++ b/libcxx/include/limits @@ -464,18 +464,18 @@ class _LIBCPP_TEMPLATE_VIS numeric_limits : private __libcpp_numeric_limits<_Tp> typedef typename __base::type type; public: - static _LIBCPP_CONSTEXPR const bool is_specialized = __base::is_specialized; + static inline _LIBCPP_CONSTEXPR const bool is_specialized = __base::is_specialized; [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __base::min(); } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __base::max(); } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return __base::lowest(); } - static _LIBCPP_CONSTEXPR const int digits = __base::digits; - static _LIBCPP_CONSTEXPR const int digits10 = __base::digits10; - static _LIBCPP_CONSTEXPR const int max_digits10 = __base::max_digits10; - static _LIBCPP_CONSTEXPR const bool is_signed = __base::is_signed; - static _LIBCPP_CONSTEXPR const bool is_integer = __base::is_integer; - static _LIBCPP_CONSTEXPR const bool is_exact = __base::is_exact; - static _LIBCPP_CONSTEXPR const int radix = __base::radix; + static inline _LIBCPP_CONSTEXPR const int digits = __base::digits; + static inline _LIBCPP_CONSTEXPR const int digits10 = __base::digits10; + static inline _LIBCPP_CONSTEXPR const int max_digits10 = __base::max_digits10; + static inline _LIBCPP_CONSTEXPR const bool is_signed = __base::is_signed; + static inline _LIBCPP_CONSTEXPR const bool is_integer = __base::is_integer; + static inline _LIBCPP_CONSTEXPR const bool is_exact = __base::is_exact; + static inline _LIBCPP_CONSTEXPR const int radix = __base::radix; [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __base::epsilon(); } @@ -483,17 +483,17 @@ public: return __base::round_error(); } - static _LIBCPP_CONSTEXPR const int min_exponent = __base::min_exponent; - static _LIBCPP_CONSTEXPR const int min_exponent10 = __base::min_exponent10; - static _LIBCPP_CONSTEXPR const int max_exponent = __base::max_exponent; - static _LIBCPP_CONSTEXPR const int max_exponent10 = __base::max_exponent10; + static inline _LIBCPP_CONSTEXPR const int min_exponent = __base::min_exponent; + static inline _LIBCPP_CONSTEXPR const int min_exponent10 = __base::min_exponent10; + static inline _LIBCPP_CONSTEXPR const int max_exponent = __base::max_exponent; + static inline _LIBCPP_CONSTEXPR const int max_exponent10 = __base::max_exponent10; - static _LIBCPP_CONSTEXPR const bool has_infinity = __base::has_infinity; - static _LIBCPP_CONSTEXPR const bool has_quiet_NaN = __base::has_quiet_NaN; - static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = __base::has_signaling_NaN; + static inline _LIBCPP_CONSTEXPR const bool has_infinity = __base::has_infinity; + static inline _LIBCPP_CONSTEXPR const bool has_quiet_NaN = __base::has_quiet_NaN; + static inline _LIBCPP_CONSTEXPR const bool has_signaling_NaN = __base::has_signaling_NaN; _LIBCPP_SUPPRESS_DEPRECATED_PUSH - static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = __base::has_denorm; - static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = __base::has_denorm_loss; + static inline _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = __base::has_denorm; + static inline _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = __base::has_denorm_loss; _LIBCPP_SUPPRESS_DEPRECATED_POP [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __base::infinity(); @@ -508,62 +508,15 @@ public: return __base::denorm_min(); } - static _LIBCPP_CONSTEXPR const bool is_iec559 = __base::is_iec559; - static _LIBCPP_CONSTEXPR const bool is_bounded = __base::is_bounded; - static _LIBCPP_CONSTEXPR const bool is_modulo = __base::is_modulo; + static inline _LIBCPP_CONSTEXPR const bool is_iec559 = __base::is_iec559; + static inline _LIBCPP_CONSTEXPR const bool is_bounded = __base::is_bounded; + static inline _LIBCPP_CONSTEXPR const bool is_modulo = __base::is_modulo; - static _LIBCPP_CONSTEXPR const bool traps = __base::traps; - static _LIBCPP_CONSTEXPR const bool tinyness_before = __base::tinyness_before; - static _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style; + static inline _LIBCPP_CONSTEXPR const bool traps = __base::traps; + static inline _LIBCPP_CONSTEXPR const bool tinyness_before = __base::tinyness_before; + static inline _LIBCPP_CONSTEXPR const float_round_style round_style = __base::round_style; }; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_specialized; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::digits; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::digits10; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_digits10; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_signed; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_integer; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_exact; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::radix; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::min_exponent; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::min_exponent10; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_exponent; -template -_LIBCPP_CONSTEXPR const int numeric_limits<_Tp>::max_exponent10; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_infinity; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_quiet_NaN; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_signaling_NaN; -template -_LIBCPP_CONSTEXPR const float_denorm_style numeric_limits<_Tp>::has_denorm; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::has_denorm_loss; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_iec559; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_bounded; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::is_modulo; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::traps; -template -_LIBCPP_CONSTEXPR const bool numeric_limits<_Tp>::tinyness_before; -template -_LIBCPP_CONSTEXPR const float_round_style numeric_limits<_Tp>::round_style; - template class _LIBCPP_TEMPLATE_VIS numeric_limits : public numeric_limits<_Tp> {}; diff --git a/libcxx/include/list b/libcxx/include/list index 3b8399e26a23195104da953e4ccb51f4d2bf7973..22629ffb1427e01f34805a76420d57775b769dcc 100644 --- a/libcxx/include/list +++ b/libcxx/include/list @@ -504,13 +504,8 @@ protected: return __node_pointer_traits::__unsafe_link_pointer_cast(const_cast<__node_base&>(__end_).__self()); } - _LIBCPP_HIDE_FROM_ABI size_type& __sz() _NOEXCEPT { return __size_; } - _LIBCPP_HIDE_FROM_ABI const size_type& __sz() const _NOEXCEPT { return __size_; } - _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __node_alloc_; } - _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __node_alloc_; } - _LIBCPP_HIDE_FROM_ABI size_type __node_alloc_max_size() const _NOEXCEPT { - return __node_alloc_traits::max_size(__node_alloc()); + return __node_alloc_traits::max_size(__node_alloc_); } _LIBCPP_HIDE_FROM_ABI static void __unlink_nodes(__base_pointer __f, __base_pointer __l) _NOEXCEPT; @@ -522,7 +517,7 @@ protected: #endif _LIBCPP_HIDE_FROM_ABI ~__list_imp(); _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __sz() == 0; } + _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; } _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__end_.__next_); } _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__end_.__next_); } @@ -550,8 +545,7 @@ protected: template _LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__base_pointer __prev, __base_pointer __next, _Args&&... __args) { - __node_allocator& __alloc = __node_alloc(); - __allocation_guard<__node_allocator> __guard(__alloc, 1); + __allocation_guard<__node_allocator> __guard(__node_alloc_, 1); // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value // held inside the node, since we need to use the allocator's construct() method for that. // @@ -562,31 +556,30 @@ protected: // Now construct the value_type using the allocator's construct() method. __node_alloc_traits::construct( - __alloc, std::addressof(__guard.__get()->__get_value()), std::forward<_Args>(__args)...); + __node_alloc_, std::addressof(__guard.__get()->__get_value()), std::forward<_Args>(__args)...); return __guard.__release_ptr(); } _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) { // For the same reason as above, we use the allocator's destroy() method for the value_type, // but not for the node itself. - __node_allocator& __alloc = __node_alloc(); - __node_alloc_traits::destroy(__alloc, std::addressof(__node->__get_value())); + __node_alloc_traits::destroy(__node_alloc_, std::addressof(__node->__get_value())); std::__destroy_at(std::addressof(*__node)); - __node_alloc_traits::deallocate(__alloc, __node, 1); + __node_alloc_traits::deallocate(__node_alloc_, __node, 1); } private: _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c, true_type) { - if (__node_alloc() != __c.__node_alloc()) + if (__node_alloc_ != __c.__node_alloc_) clear(); - __node_alloc() = __c.__node_alloc(); + __node_alloc_ = __c.__node_alloc_; } _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp&, false_type) {} _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c, true_type) _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) { - __node_alloc() = std::move(__c.__node_alloc()); + __node_alloc_ = std::move(__c.__node_alloc_); } _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp&, false_type) _NOEXCEPT {} @@ -628,7 +621,7 @@ void __list_imp<_Tp, _Alloc>::clear() _NOEXCEPT { __base_pointer __f = __end_.__next_; __base_pointer __l = __end_as_link(); __unlink_nodes(__f, __l->__prev_); - __sz() = 0; + __size_ = 0; while (__f != __l) { __node_pointer __np = __f->__as_node(); __f = __f->__next_; @@ -646,18 +639,18 @@ void __list_imp<_Tp, _Alloc>::swap(__list_imp& __c) #endif { _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR( - __alloc_traits::propagate_on_container_swap::value || this->__node_alloc() == __c.__node_alloc(), + __alloc_traits::propagate_on_container_swap::value || this->__node_alloc_ == __c.__node_alloc_, "list::swap: Either propagate_on_container_swap must be true" " or the allocators must compare equal"); using std::swap; - std::__swap_allocator(__node_alloc(), __c.__node_alloc()); - swap(__sz(), __c.__sz()); + std::__swap_allocator(__node_alloc_, __c.__node_alloc_); + swap(__size_, __c.__size_); swap(__end_, __c.__end_); - if (__sz() == 0) + if (__size_ == 0) __end_.__next_ = __end_.__prev_ = __end_as_link(); else __end_.__prev_->__next_ = __end_.__next_->__prev_ = __end_as_link(); - if (__c.__sz() == 0) + if (__c.__size_ == 0) __c.__end_.__next_ = __c.__end_.__prev_ = __c.__end_as_link(); else __c.__end_.__prev_->__next_ = __c.__end_.__next_->__prev_ = __c.__end_as_link(); @@ -758,10 +751,10 @@ public: _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const _NOEXCEPT; - _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __base::__sz(); } + _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return this->__size_; } [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __base::empty(); } _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT { - return std::min(__base::__node_alloc_max_size(), numeric_limits::max()); + return std::min(this->__node_alloc_max_size(), numeric_limits::max()); } _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __base::begin(); } @@ -985,7 +978,7 @@ inline void list<_Tp, _Alloc>::__link_nodes_at_back(__base_pointer __f, __base_p template inline typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::__iterator(size_type __n) { - return __n <= __base::__sz() / 2 ? std::next(begin(), __n) : std::prev(end(), __base::__sz() - __n); + return __n <= this->__size_ / 2 ? std::next(begin(), __n) : std::prev(end(), this->__size_ - __n); } template @@ -1028,7 +1021,7 @@ list<_Tp, _Alloc>::list(_InpIter __f, _InpIter __l, const allocator_type& __a) : template list<_Tp, _Alloc>::list(const list& __c) - : __base(__node_alloc_traits::select_on_container_copy_construction(__c.__node_alloc())) { + : __base(__node_alloc_traits::select_on_container_copy_construction(__c.__node_alloc_)) { for (const_iterator __i = __c.begin(), __e = __c.end(); __i != __e; ++__i) push_back(*__i); } @@ -1055,7 +1048,7 @@ list<_Tp, _Alloc>::list(initializer_list __il) { template inline list<_Tp, _Alloc>::list(list&& __c) noexcept(is_nothrow_move_constructible<__node_allocator>::value) - : __base(std::move(__c.__node_alloc())) { + : __base(std::move(__c.__node_alloc_)) { splice(end(), __c); } @@ -1079,7 +1072,7 @@ inline list<_Tp, _Alloc>& list<_Tp, _Alloc>::operator=(list&& __c) noexcept( template void list<_Tp, _Alloc>::__move_assign(list& __c, false_type) { - if (__base::__node_alloc() != __c.__node_alloc()) { + if (this->__node_alloc_ != __c.__node_alloc_) { typedef move_iterator _Ip; assign(_Ip(__c.begin()), _Ip(__c.end())); } else @@ -1138,14 +1131,14 @@ void list<_Tp, _Alloc>::assign(size_type __n, const value_type& __x) { template inline _Alloc list<_Tp, _Alloc>::get_allocator() const _NOEXCEPT { - return allocator_type(__base::__node_alloc()); + return allocator_type(this->__node_alloc_); } template typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __p, const value_type& __x) { __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x); __link_nodes(__p.__ptr_, __node->__as_link(), __node->__as_link()); - ++__base::__sz(); + ++this->__size_; return iterator(__node->__as_link()); } @@ -1179,7 +1172,7 @@ list<_Tp, _Alloc>::insert(const_iterator __p, size_type __n, const value_type& _ } #endif // _LIBCPP_HAS_EXCEPTIONS __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); - __base::__sz() += __ds; + this->__size_ += __ds; } return __r; } @@ -1221,7 +1214,7 @@ list<_Tp, _Alloc>::__insert_with_sentinel(const_iterator __p, _Iterator __f, _Se } #endif // _LIBCPP_HAS_EXCEPTIONS __link_nodes(__p.__ptr_, __r.__ptr_, __e.__ptr_); - __base::__sz() += __ds; + this->__size_ += __ds; } return __r; } @@ -1231,7 +1224,7 @@ void list<_Tp, _Alloc>::push_front(const value_type& __x) { __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x); __base_pointer __nl = __node->__as_link(); __link_nodes_at_front(__nl, __nl); - ++__base::__sz(); + ++this->__size_; } template @@ -1239,7 +1232,7 @@ void list<_Tp, _Alloc>::push_back(const value_type& __x) { __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x); __base_pointer __nl = __node->__as_link(); __link_nodes_at_back(__nl, __nl); - ++__base::__sz(); + ++this->__size_; } #ifndef _LIBCPP_CXX03_LANG @@ -1249,7 +1242,7 @@ void list<_Tp, _Alloc>::push_front(value_type&& __x) { __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::move(__x)); __base_pointer __nl = __node->__as_link(); __link_nodes_at_front(__nl, __nl); - ++__base::__sz(); + ++this->__size_; } template @@ -1257,7 +1250,7 @@ void list<_Tp, _Alloc>::push_back(value_type&& __x) { __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::move(__x)); __base_pointer __nl = __node->__as_link(); __link_nodes_at_back(__nl, __nl); - ++__base::__sz(); + ++this->__size_; } template @@ -1272,7 +1265,7 @@ list<_Tp, _Alloc>::emplace_front(_Args&&... __args) { this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::forward<_Args>(__args)...); __base_pointer __nl = __node->__as_link(); __link_nodes_at_front(__nl, __nl); - ++__base::__sz(); + ++this->__size_; # if _LIBCPP_STD_VER >= 17 return __node->__get_value(); # endif @@ -1290,7 +1283,7 @@ list<_Tp, _Alloc>::emplace_back(_Args&&... __args) { this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::forward<_Args>(__args)...); __base_pointer __nl = __node->__as_link(); __link_nodes_at_back(__nl, __nl); - ++__base::__sz(); + ++this->__size_; # if _LIBCPP_STD_VER >= 17 return __node->__get_value(); # endif @@ -1303,7 +1296,7 @@ typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::emplace(const_iterator _ this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::forward<_Args>(__args)...); __base_pointer __nl = __node->__as_link(); __link_nodes(__p.__ptr_, __nl, __nl); - ++__base::__sz(); + ++this->__size_; return iterator(__nl); } @@ -1312,7 +1305,7 @@ typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::insert(const_iterator __ __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, std::move(__x)); __base_pointer __nl = __node->__as_link(); __link_nodes(__p.__ptr_, __nl, __nl); - ++__base::__sz(); + ++this->__size_; return iterator(__nl); } @@ -1323,7 +1316,7 @@ void list<_Tp, _Alloc>::pop_front() { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_front() called with empty list"); __base_pointer __n = __base::__end_.__next_; __base::__unlink_nodes(__n, __n); - --__base::__sz(); + --this->__size_; this->__delete_node(__n->__as_node()); } @@ -1332,7 +1325,7 @@ void list<_Tp, _Alloc>::pop_back() { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "list::pop_back() called on an empty list"); __base_pointer __n = __base::__end_.__prev_; __base::__unlink_nodes(__n, __n); - --__base::__sz(); + --this->__size_; this->__delete_node(__n->__as_node()); } @@ -1342,7 +1335,7 @@ typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __p __base_pointer __n = __p.__ptr_; __base_pointer __r = __n->__next_; __base::__unlink_nodes(__n, __n); - --__base::__sz(); + --this->__size_; this->__delete_node(__n->__as_node()); return iterator(__r); } @@ -1354,7 +1347,7 @@ typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __f while (__f != __l) { __base_pointer __n = __f.__ptr_; ++__f; - --__base::__sz(); + --this->__size_; this->__delete_node(__n->__as_node()); } } @@ -1363,10 +1356,10 @@ typename list<_Tp, _Alloc>::iterator list<_Tp, _Alloc>::erase(const_iterator __f template void list<_Tp, _Alloc>::resize(size_type __n) { - if (__n < __base::__sz()) + if (__n < this->__size_) erase(__iterator(__n), end()); - else if (__n > __base::__sz()) { - __n -= __base::__sz(); + else if (__n > this->__size_) { + __n -= this->__size_; size_type __ds = 0; __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr); ++__ds; @@ -1392,16 +1385,16 @@ void list<_Tp, _Alloc>::resize(size_type __n) { } #endif // _LIBCPP_HAS_EXCEPTIONS __link_nodes_at_back(__r.__ptr_, __e.__ptr_); - __base::__sz() += __ds; + this->__size_ += __ds; } } template void list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) { - if (__n < __base::__sz()) + if (__n < this->__size_) erase(__iterator(__n), end()); - else if (__n > __base::__sz()) { - __n -= __base::__sz(); + else if (__n > this->__size_) { + __n -= this->__size_; size_type __ds = 0; __node_pointer __node = this->__create_node(/* prev = */ nullptr, /* next = */ nullptr, __x); ++__ds; @@ -1428,7 +1421,7 @@ void list<_Tp, _Alloc>::resize(size_type __n, const value_type& __x) { } #endif // _LIBCPP_HAS_EXCEPTIONS __link_nodes(__base::__end_as_link(), __r.__ptr_, __e.__ptr_); - __base::__sz() += __ds; + this->__size_ += __ds; } } @@ -1441,8 +1434,8 @@ void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c) { __base_pointer __l = __c.__end_.__prev_; __base::__unlink_nodes(__f, __l); __link_nodes(__p.__ptr_, __f, __l); - __base::__sz() += __c.__sz(); - __c.__sz() = 0; + this->__size_ += __c.__size_; + __c.__size_ = 0; } } @@ -1452,8 +1445,8 @@ void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __i __base_pointer __f = __i.__ptr_; __base::__unlink_nodes(__f, __f); __link_nodes(__p.__ptr_, __f, __f); - --__c.__sz(); - ++__base::__sz(); + --__c.__size_; + ++this->__size_; } } @@ -1465,8 +1458,8 @@ void list<_Tp, _Alloc>::splice(const_iterator __p, list& __c, const_iterator __f __base_pointer __last = __l.__ptr_; if (this != std::addressof(__c)) { size_type __s = std::distance(__f, __l) + 1; - __c.__sz() -= __s; - __base::__sz() += __s; + __c.__size_ -= __s; + this->__size_ += __s; } __base::__unlink_nodes(__first, __last); __link_nodes(__p.__ptr_, __first, __last); @@ -1548,8 +1541,8 @@ void list<_Tp, _Alloc>::merge(list& __c, _Comp __comp) { iterator __m2 = std::next(__f2); for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2, (void)++__ds) ; - __base::__sz() += __ds; - __c.__sz() -= __ds; + this->__size_ += __ds; + __c.__size_ -= __ds; __base_pointer __f = __f2.__ptr_; __base_pointer __l = __m2.__ptr_->__prev_; __f2 = __m2; @@ -1572,7 +1565,7 @@ inline void list<_Tp, _Alloc>::sort() { template template inline void list<_Tp, _Alloc>::sort(_Comp __comp) { - __sort(begin(), end(), __base::__sz(), __comp); + __sort(begin(), end(), this->__size_, __comp); } template @@ -1632,7 +1625,7 @@ list<_Tp, _Alloc>::__sort(iterator __f1, iterator __e2, size_type __n, _Comp& __ template void list<_Tp, _Alloc>::reverse() _NOEXCEPT { - if (__base::__sz() > 1) { + if (this->__size_ > 1) { iterator __e = end(); for (iterator __i = begin(); __i.__ptr_ != __e.__ptr_;) { std::swap(__i.__ptr_->__prev_, __i.__ptr_->__next_); diff --git a/libcxx/include/locale b/libcxx/include/locale index c887140f38c224502b75a6373d44d1ebb821ab77..65f5c6ba52f73641cd04ec27ef4983a79950d770 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -203,6 +203,7 @@ template class messages_byname; # include <__iterator/istreambuf_iterator.h> # include <__iterator/ostreambuf_iterator.h> # include <__locale> +# include <__locale_dir/pad_and_output.h> # include <__memory/unique_ptr.h> # include <__type_traits/make_unsigned.h> # include @@ -1239,66 +1240,6 @@ protected: template locale::id num_put<_CharT, _OutputIterator>::id; -template -_LIBCPP_HIDE_FROM_ABI _OutputIterator __pad_and_output( - _OutputIterator __s, const _CharT* __ob, const _CharT* __op, const _CharT* __oe, ios_base& __iob, _CharT __fl) { - streamsize __sz = __oe - __ob; - streamsize __ns = __iob.width(); - if (__ns > __sz) - __ns -= __sz; - else - __ns = 0; - for (; __ob < __op; ++__ob, ++__s) - *__s = *__ob; - for (; __ns; --__ns, ++__s) - *__s = __fl; - for (; __ob < __oe; ++__ob, ++__s) - *__s = *__ob; - __iob.width(0); - return __s; -} - -template -_LIBCPP_HIDE_FROM_ABI ostreambuf_iterator<_CharT, _Traits> __pad_and_output( - ostreambuf_iterator<_CharT, _Traits> __s, - const _CharT* __ob, - const _CharT* __op, - const _CharT* __oe, - ios_base& __iob, - _CharT __fl) { - if (__s.__sbuf_ == nullptr) - return __s; - streamsize __sz = __oe - __ob; - streamsize __ns = __iob.width(); - if (__ns > __sz) - __ns -= __sz; - else - __ns = 0; - streamsize __np = __op - __ob; - if (__np > 0) { - if (__s.__sbuf_->sputn(__ob, __np) != __np) { - __s.__sbuf_ = nullptr; - return __s; - } - } - if (__ns > 0) { - basic_string<_CharT, _Traits> __sp(__ns, __fl); - if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns) { - __s.__sbuf_ = nullptr; - return __s; - } - } - __np = __oe - __op; - if (__np > 0) { - if (__s.__sbuf_->sputn(__op, __np) != __np) { - __s.__sbuf_ = nullptr; - return __s; - } - } - __iob.width(0); - return __s; -} - template _OutputIterator num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan index 29190e4a9953ed0d59ffcbcee349fc8faf4c5b3b..d6191a197e15c6348c40c885971f852421e07248 100644 --- a/libcxx/include/mdspan +++ b/libcxx/include/mdspan @@ -426,13 +426,4 @@ namespace std { # pragma GCC system_header #endif -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 -# include -# include -# include -# include -# include -# include -#endif - #endif // _LIBCPP_MDSPAN diff --git a/libcxx/include/memory_resource b/libcxx/include/memory_resource index e98ca20aa058c33cdf951c3a06cf5bae618da59f..7de69e67b7c0629fd91df1f282d8152933507804 100644 --- a/libcxx/include/memory_resource +++ b/libcxx/include/memory_resource @@ -66,15 +66,6 @@ namespace std::pmr { # pragma GCC system_header #endif -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 14 -# include -# include -# include -# include -# include -# include -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include #endif diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 9027c28632dcda2752ae0b1dcda135cdfd73a9a1..4e06a68c6a6b614515be9c4c83248b85ab3e010c 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -844,7 +844,6 @@ module std [system] { module atomic { module aliases { header "__atomic/aliases.h" } - module atomic_base { header "__atomic/atomic_base.h" } module atomic_flag { header "__atomic/atomic_flag.h" } module atomic_init { header "__atomic/atomic_init.h" } module atomic_lock_free { header "__atomic/atomic_lock_free.h" } @@ -1460,7 +1459,9 @@ module std [system] { module locale { header "locale" - header "__locale_dir/locale_guard.h" + + module locale_guard { header "__locale_dir/locale_guard.h" } + module pad_and_output { header "__locale_dir/pad_and_output.h" } module support { header "__locale_dir/locale_base_api.h" @@ -1542,6 +1543,7 @@ module std [system] { export std.algorithm.in_out_result } module raw_storage_iterator { header "__memory/raw_storage_iterator.h" } + module shared_count { header "__memory/shared_count.h" } module shared_ptr { header "__memory/shared_ptr.h" } module swap_allocator { header "__memory/swap_allocator.h" } module temp_value { header "__memory/temp_value.h" } @@ -1640,6 +1642,7 @@ module std [system] { header "__ostream/print.h" export * } + module put_character_sequence { header "__ostream/put_character_sequence.h" } header "ostream" export * @@ -1920,6 +1923,7 @@ module std [system] { } module error_condition { header "__system_error/error_condition.h" } module system_error { header "__system_error/system_error.h" } + module throw_system_error { header "__system_error/throw_system_error.h" } header "system_error" export * diff --git a/libcxx/include/mutex b/libcxx/include/mutex index 60a7c9945909ce78c21dff3586b7ee1fedbde1cf..ecbfc5607dcc7828d56a7976edc7fb7fa1019d10 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -190,7 +190,6 @@ template #include <__chrono/time_point.h> #include <__condition_variable/condition_variable.h> #include <__config> -#include <__memory/shared_ptr.h> #include <__mutex/lock_guard.h> #include <__mutex/mutex.h> #include <__mutex/once_flag.h> diff --git a/libcxx/include/print b/libcxx/include/print index 7c808300701383358dfea0335061b039333fa596..8a8b686d18f34d83ed2c88024fe9351025b0e013 100644 --- a/libcxx/include/print +++ b/libcxx/include/print @@ -36,7 +36,7 @@ namespace std { #include <__assert> #include <__concepts/same_as.h> #include <__config> -#include <__system_error/system_error.h> +#include <__system_error/throw_system_error.h> #include <__utility/forward.h> #include #include diff --git a/libcxx/include/ranges b/libcxx/include/ranges index b17a399e0ed65b2f05697004cea1382b191b4433..d8ee6f75e8b23cab524273f3864e9881ac1f76e4 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -446,14 +446,6 @@ namespace std { # pragma GCC system_header #endif -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 -# include -# include -# include -# include -# include -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include diff --git a/libcxx/include/ratio b/libcxx/include/ratio index b989c272aaee6ad8d775de7bfd68cc35a3bb9d14..bd262437db34f67eda8ba3ce2935b0744b9867fc 100644 --- a/libcxx/include/ratio +++ b/libcxx/include/ratio @@ -99,38 +99,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD // __static_gcd template -struct __static_gcd { - static const intmax_t value = __static_gcd<_Yp, _Xp % _Yp>::value; -}; +inline const intmax_t __static_gcd = __static_gcd<_Yp, _Xp % _Yp>; template -struct __static_gcd<_Xp, 0> { - static const intmax_t value = _Xp; -}; +inline const intmax_t __static_gcd<_Xp, 0> = _Xp; template <> -struct __static_gcd<0, 0> { - static const intmax_t value = 1; -}; +inline const intmax_t __static_gcd<0, 0> = 1; // __static_lcm template -struct __static_lcm { - static const intmax_t value = _Xp / __static_gcd<_Xp, _Yp>::value * _Yp; -}; +inline const intmax_t __static_lcm = _Xp / __static_gcd<_Xp, _Yp> * _Yp; template -struct __static_abs { - static const intmax_t value = _Xp < 0 ? -_Xp : _Xp; -}; +inline const intmax_t __static_abs = _Xp < 0 ? -_Xp : _Xp; template -struct __static_sign { - static const intmax_t value = _Xp == 0 ? 0 : (_Xp < 0 ? -1 : 1); -}; +inline const intmax_t __static_sign = _Xp == 0 ? 0 : (_Xp < 0 ? -1 : 1); -template ::value> +template > class __ll_add; template @@ -161,7 +149,7 @@ public: static const intmax_t value = _Xp + _Yp; }; -template ::value> +template > class __ll_sub; template @@ -197,8 +185,8 @@ class __ll_mul { static const intmax_t nan = (1LL << (sizeof(intmax_t) * CHAR_BIT - 1)); static const intmax_t min = nan + 1; static const intmax_t max = -min; - static const intmax_t __a_x = __static_abs<_Xp>::value; - static const intmax_t __a_y = __static_abs<_Yp>::value; + static const intmax_t __a_x = __static_abs<_Xp>; + static const intmax_t __a_y = __static_abs<_Yp>; static_assert(_Xp != nan && _Yp != nan && __a_x <= max / __a_y, "overflow in __ll_mul"); @@ -239,31 +227,26 @@ public: template class _LIBCPP_TEMPLATE_VIS ratio { - static_assert(__static_abs<_Num>::value >= 0, "ratio numerator is out of range"); + static_assert(__static_abs<_Num> >= 0, "ratio numerator is out of range"); static_assert(_Den != 0, "ratio divide by 0"); - static_assert(__static_abs<_Den>::value > 0, "ratio denominator is out of range"); - static _LIBCPP_CONSTEXPR const intmax_t __na = __static_abs<_Num>::value; - static _LIBCPP_CONSTEXPR const intmax_t __da = __static_abs<_Den>::value; - static _LIBCPP_CONSTEXPR const intmax_t __s = __static_sign<_Num>::value * __static_sign<_Den>::value; - static _LIBCPP_CONSTEXPR const intmax_t __gcd = __static_gcd<__na, __da>::value; + static_assert(__static_abs<_Den> > 0, "ratio denominator is out of range"); + static _LIBCPP_CONSTEXPR const intmax_t __na = __static_abs<_Num>; + static _LIBCPP_CONSTEXPR const intmax_t __da = __static_abs<_Den>; + static _LIBCPP_CONSTEXPR const intmax_t __s = __static_sign<_Num> * __static_sign<_Den>; + static _LIBCPP_CONSTEXPR const intmax_t __gcd = __static_gcd<__na, __da>; public: - static _LIBCPP_CONSTEXPR const intmax_t num = __s * __na / __gcd; - static _LIBCPP_CONSTEXPR const intmax_t den = __da / __gcd; + static inline _LIBCPP_CONSTEXPR const intmax_t num = __s * __na / __gcd; + static inline _LIBCPP_CONSTEXPR const intmax_t den = __da / __gcd; typedef ratio type; }; -template -_LIBCPP_CONSTEXPR const intmax_t ratio<_Num, _Den>::num; - -template -_LIBCPP_CONSTEXPR const intmax_t ratio<_Num, _Den>::den; - template -struct __is_ratio : false_type {}; +inline const bool __is_ratio_v = false; + template -struct __is_ratio > : true_type {}; +inline const bool __is_ratio_v > = true; typedef ratio<1LL, 1000000000000000000LL> atto; typedef ratio<1LL, 1000000000000000LL> femto; @@ -285,11 +268,11 @@ typedef ratio<1000000000000000000LL, 1LL> exa; template struct __ratio_multiply { private: - static const intmax_t __gcd_n1_d2 = __static_gcd<_R1::num, _R2::den>::value; - static const intmax_t __gcd_d1_n2 = __static_gcd<_R1::den, _R2::num>::value; + static const intmax_t __gcd_n1_d2 = __static_gcd<_R1::num, _R2::den>; + static const intmax_t __gcd_d1_n2 = __static_gcd<_R1::den, _R2::num>; - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); public: typedef typename ratio< __ll_mul<_R1::num / __gcd_n1_d2, _R2::num / __gcd_d1_n2>::value, @@ -311,11 +294,11 @@ struct _LIBCPP_TEMPLATE_VIS ratio_multiply : public __ratio_multiply<_R1, _R2>:: template struct __ratio_divide { private: - static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; - static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; + static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>; + static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>; - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); public: typedef typename ratio< __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value, @@ -337,11 +320,11 @@ struct _LIBCPP_TEMPLATE_VIS ratio_divide : public __ratio_divide<_R1, _R2>::type template struct __ratio_add { private: - static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; - static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; + static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>; + static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>; - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); public: typedef typename ratio_multiply< @@ -366,11 +349,11 @@ struct _LIBCPP_TEMPLATE_VIS ratio_add : public __ratio_add<_R1, _R2>::type {}; template struct __ratio_subtract { private: - static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value; - static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value; + static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>; + static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>; - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); public: typedef typename ratio_multiply< @@ -396,14 +379,14 @@ struct _LIBCPP_TEMPLATE_VIS ratio_subtract : public __ratio_subtract<_R1, _R2>:: template struct _LIBCPP_TEMPLATE_VIS ratio_equal : _BoolConstant<(_R1::num == _R2::num && _R1::den == _R2::den)> { - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); }; template struct _LIBCPP_TEMPLATE_VIS ratio_not_equal : _BoolConstant::value> { - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); }; // ratio_less @@ -439,10 +422,7 @@ struct __ratio_less1<_R1, _R2, _Odd, _Qp, _M1, _Qp, _M2> { static const bool value = __ratio_less1, ratio<_R2::den, _M2>, !_Odd>::value; }; -template ::value, - intmax_t _S2 = __static_sign<_R2::num>::value> +template , intmax_t _S2 = __static_sign<_R2::num> > struct __ratio_less { static const bool value = _S1 < _S2; }; @@ -459,32 +439,30 @@ struct __ratio_less<_R1, _R2, -1LL, -1LL> { template struct _LIBCPP_TEMPLATE_VIS ratio_less : _BoolConstant<__ratio_less<_R1, _R2>::value> { - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); }; template struct _LIBCPP_TEMPLATE_VIS ratio_less_equal : _BoolConstant::value> { - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); }; template struct _LIBCPP_TEMPLATE_VIS ratio_greater : _BoolConstant::value> { - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); }; template struct _LIBCPP_TEMPLATE_VIS ratio_greater_equal : _BoolConstant::value> { - static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); - static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R1>, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template"); + static_assert(__is_ratio_v<_R2>, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template"); }; template -struct __ratio_gcd { - typedef ratio<__static_gcd<_R1::num, _R2::num>::value, __static_lcm<_R1::den, _R2::den>::value> type; -}; +using __ratio_gcd = ratio<__static_gcd<_R1::num, _R2::num>, __static_lcm<_R1::den, _R2::den> >; #if _LIBCPP_STD_VER >= 17 template diff --git a/libcxx/include/semaphore b/libcxx/include/semaphore index 05c85bc810603e6d222e90bfc2c37c60e06cd2a4..c594df459c93fc8da99e96acc3cf234449522b6d 100644 --- a/libcxx/include/semaphore +++ b/libcxx/include/semaphore @@ -50,7 +50,7 @@ using binary_semaphore = counting_semaphore<1>; // since C++20 #if _LIBCPP_HAS_THREADS # include <__assert> -# include <__atomic/atomic_base.h> +# include <__atomic/atomic.h> # include <__atomic/atomic_sync.h> # include <__atomic/memory_order.h> # include <__chrono/time_point.h> @@ -83,7 +83,7 @@ functions. It avoids contention against users' own use of those facilities. # define _LIBCPP_SEMAPHORE_MAX (numeric_limits::max()) class __atomic_semaphore_base { - __atomic_base __a_; + atomic __a_; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __atomic_semaphore_base(ptrdiff_t __count) : __a_(__count) {} diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex index 68030e9ce8ff4edbd8b37b6ca554294628d28f13..2552119405419cd237e52afb6ca5eb76239b6e75 100644 --- a/libcxx/include/shared_mutex +++ b/libcxx/include/shared_mutex @@ -134,7 +134,7 @@ template # include <__mutex/mutex.h> # include <__mutex/tag_types.h> # include <__mutex/unique_lock.h> -# include <__system_error/system_error.h> +# include <__system_error/throw_system_error.h> # include <__utility/swap.h> # include # include diff --git a/libcxx/include/string b/libcxx/include/string index a3f0bdea7ccb1d8867c4580c764b4c0e86ad53a9..bf7fc3c37ecd7a8eaa449e4d7f23eb5c6d64bf49 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -2258,11 +2258,11 @@ private: return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v)); } - [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void __throw_length_error() const { + [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_length_error() { std::__throw_length_error("basic_string"); } - [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { + [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI static void __throw_out_of_range() { std::__throw_out_of_range("basic_string"); } @@ -3374,7 +3374,7 @@ template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) { __annotate_delete(); - auto __guard = std::__make_scope_guard(__annotate_new_size(*this)); + auto __guard = std::__make_scope_guard(__annotate_new_size(*this)); size_type __cap = capacity(); size_type __sz = size(); diff --git a/libcxx/include/strstream b/libcxx/include/strstream index 9ff4024a7c7e212a4fc74e1f9add4e00e5389fe9..b263fe1a76ad227a6651649443e11afcccefcfc6 100644 --- a/libcxx/include/strstream +++ b/libcxx/include/strstream @@ -130,8 +130,9 @@ private: */ #include <__config> +#include <__ostream/basic_ostream.h> #include -#include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/thread b/libcxx/include/thread index bfe7e4a4c51e5c70cd91176bf0da22b2f3e00590..d7c3f704ad672bbdb0ff1ae31f8a9c0bdf5e9766 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -90,11 +90,17 @@ void sleep_for(const chrono::duration& rel_time); #if _LIBCPP_HAS_THREADS -# include <__thread/formatter.h> -# include <__thread/jthread.h> -# include <__thread/support.h> # include <__thread/this_thread.h> # include <__thread/thread.h> + +# if _LIBCPP_STD_VER >= 20 +# include <__thread/jthread.h> +# endif + +# if _LIBCPP_STD_VER >= 23 +# include <__thread/formatter.h> +# endif + # include // standard-mandated includes @@ -108,13 +114,6 @@ void sleep_for(const chrono::duration& rel_time); #endif // _LIBCPP_HAS_THREADS -#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) -# include -# include -# include -# include -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17 # include #endif diff --git a/libcxx/src/barrier.cpp b/libcxx/src/barrier.cpp index 69601bfeec0546ff5b29084010eaad4bee9084e0..b97c7bd73b74cd5a82c49805fd25a0c2ffd37037 100644 --- a/libcxx/src/barrier.cpp +++ b/libcxx/src/barrier.cpp @@ -17,7 +17,7 @@ class __barrier_algorithm_base { public: struct alignas(64) /* naturally-align the heap state */ __state_t { struct { - __atomic_base<__barrier_phase_t> __phase{0}; + atomic<__barrier_phase_t> __phase{0}; } __tickets[64]; }; diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp index f17ea5542bd99d7d84d6621e00a2304a70340843..35105693b9f900eb8a9b899a182f027216fb8ab0 100644 --- a/libcxx/src/chrono.cpp +++ b/libcxx/src/chrono.cpp @@ -12,7 +12,7 @@ # define _LARGE_TIME_API #endif -#include <__system_error/system_error.h> +#include <__system_error/throw_system_error.h> #include // errno #include @@ -134,7 +134,10 @@ static system_clock::time_point __libcpp_system_clock_now() { #endif +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") const bool system_clock::is_steady; +_LIBCPP_DIAGNOSTIC_POP system_clock::time_point system_clock::now() noexcept { return __libcpp_system_clock_now(); } @@ -226,7 +229,10 @@ static steady_clock::time_point __libcpp_steady_clock_now() { # error "Monotonic clock not implemented on this platform" # endif +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") const bool steady_clock::is_steady; +_LIBCPP_DIAGNOSTIC_POP steady_clock::time_point steady_clock::now() noexcept { return __libcpp_steady_clock_now(); } diff --git a/libcxx/src/filesystem/filesystem_clock.cpp b/libcxx/src/filesystem/filesystem_clock.cpp index 473a54a00f013a3345f54ec393f9a7bc1fbb64cc..d174ecdc9e10608ae1848d24ae0b2842831e26f2 100644 --- a/libcxx/src/filesystem/filesystem_clock.cpp +++ b/libcxx/src/filesystem/filesystem_clock.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include <__config> +#include <__system_error/throw_system_error.h> #include #include #include @@ -36,7 +37,10 @@ _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") const bool _FilesystemClock::is_steady; +_LIBCPP_DIAGNOSTIC_POP _FilesystemClock::time_point _FilesystemClock::now() noexcept { typedef chrono::duration __secs; diff --git a/libcxx/src/filesystem/path.cpp b/libcxx/src/filesystem/path.cpp index 58742442bae6b7169d8094bb8b51bb2cbdc6d3bb..9f7dc54fdf156c07154b9a52d99759492bd609c5 100644 --- a/libcxx/src/filesystem/path.cpp +++ b/libcxx/src/filesystem/path.cpp @@ -24,7 +24,10 @@ using parser::string_view_t; // path definitions /////////////////////////////////////////////////////////////////////////////// +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated") constexpr path::value_type path::preferred_separator; +_LIBCPP_DIAGNOSTIC_POP path& path::replace_extension(path const& replacement) { path p = extension(); diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp index 14c6f4473d70b90005e20db743e3d5ead6b9b977..3830e3918d2ee470e5aac2695c8bc98c4c256a1a 100644 --- a/libcxx/src/random.cpp +++ b/libcxx/src/random.cpp @@ -13,7 +13,7 @@ # define _CRT_RAND_S #endif // defined(_LIBCPP_USING_WIN32_RANDOM) -#include <__system_error/system_error.h> +#include <__system_error/throw_system_error.h> #include #include diff --git a/libcxx/src/system_error.cpp b/libcxx/src/system_error.cpp index 53838c6c6d219b751995bda1f6866cbf00009e0a..d555bca995c4547f7cbb41d36c922661ad6116e6 100644 --- a/libcxx/src/system_error.cpp +++ b/libcxx/src/system_error.cpp @@ -8,6 +8,7 @@ #include <__assert> #include <__config> +#include <__system_error/throw_system_error.h> #include <__verbose_abort> #include #include diff --git a/libcxx/test/benchmarks/CMakeLists.txt b/libcxx/test/benchmarks/CMakeLists.txt index b5a4aae82c06ab586926a016ddb8e0b9a8dbccb2..b0fe600623d964218fe3fffd843aa41f4aab9abe 100644 --- a/libcxx/test/benchmarks/CMakeLists.txt +++ b/libcxx/test/benchmarks/CMakeLists.txt @@ -35,13 +35,14 @@ ExternalProject_Add(google-benchmark SOURCE_DIR ${LLVM_THIRD_PARTY_DIR}/benchmark INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/google-benchmark CMAKE_CACHE_ARGS - -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} - -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} + -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} + -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM} -DCMAKE_BUILD_TYPE:STRING=RELEASE -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_CXX_FLAGS:STRING=${BENCHMARK_COMPILE_FLAGS} -DBENCHMARK_USE_LIBCXX:BOOL=ON -DBENCHMARK_ENABLE_TESTING:BOOL=OFF - -DBENCHMARK_CXX_LIBRARIES:STRING="${BENCHMARK_CXX_LIBRARIES}") + -DBENCHMARK_CXX_LIBRARIES:STRING=${BENCHMARK_CXX_LIBRARIES}) add_dependencies(cxx-test-depends google-benchmark) diff --git a/libcxx/test/benchmarks/ContainerBenchmarks.h b/libcxx/test/benchmarks/ContainerBenchmarks.h index 742c848328604cf4a4b04416b8739275a113ef23..38e11777f488b7bb4f407323b30f5a0a277b2554 100644 --- a/libcxx/test/benchmarks/ContainerBenchmarks.h +++ b/libcxx/test/benchmarks/ContainerBenchmarks.h @@ -11,6 +11,8 @@ #define BENCHMARK_CONTAINER_BENCHMARKS_H #include +#include +#include #include "Utilities.h" #include "benchmark/benchmark.h" @@ -149,6 +151,34 @@ void BM_EmplaceDuplicate(benchmark::State& st, Container c, GenInputs gen) { } } +template +void BM_erase_iter_in_middle(benchmark::State& st, Container, GenInputs gen) { + auto in = gen(st.range(0)); + Container c(in.begin(), in.end()); + assert(c.size() > 2); + for (auto _ : st) { + auto mid = std::next(c.begin(), c.size() / 2); + auto tmp = *mid; + auto result = c.erase(mid); // erase an element in the middle + benchmark::DoNotOptimize(result); + c.push_back(std::move(tmp)); // and then push it back at the end to avoid needing a new container + } +} + +template +void BM_erase_iter_at_start(benchmark::State& st, Container, GenInputs gen) { + auto in = gen(st.range(0)); + Container c(in.begin(), in.end()); + assert(c.size() > 2); + for (auto _ : st) { + auto it = c.begin(); + auto tmp = *it; + auto result = c.erase(it); // erase the first element + benchmark::DoNotOptimize(result); + c.push_back(std::move(tmp)); // and then push it back at the end to avoid needing a new container + } +} + template void BM_Find(benchmark::State& st, Container c, GenInputs gen) { auto in = gen(st.range(0)); diff --git a/libcxx/test/benchmarks/GenerateInput.h b/libcxx/test/benchmarks/GenerateInput.h index 0f3e9309271bb169a4e3656586b37938617066e0..db376614382bc494273df277f932bd6729ffba93 100644 --- a/libcxx/test/benchmarks/GenerateInput.h +++ b/libcxx/test/benchmarks/GenerateInput.h @@ -53,6 +53,7 @@ inline std::vector getDuplicateIntegerInputs(std::size_t N) { template inline std::vector getSortedIntegerInputs(std::size_t N) { std::vector inputs; + inputs.reserve(N); for (std::size_t i = 0; i < N; i += 1) inputs.push_back(i); return inputs; @@ -61,6 +62,7 @@ inline std::vector getSortedIntegerInputs(std::size_t N) { template std::vector getSortedLargeIntegerInputs(std::size_t N) { std::vector inputs; + inputs.reserve(N); for (std::size_t i = 0; i < N; ++i) inputs.push_back(i + N); return inputs; @@ -77,6 +79,7 @@ std::vector getSortedTopBitsIntegerInputs(std::size_t N) { template inline std::vector getReverseSortedIntegerInputs(std::size_t N) { std::vector inputs; + inputs.reserve(N); std::size_t i = N; while (i > 0) { --i; @@ -99,6 +102,7 @@ std::vector getPipeOrganIntegerInputs(std::size_t N) { template std::vector getRandomIntegerInputs(std::size_t N) { std::vector inputs; + inputs.reserve(N); for (std::size_t i = 0; i < N; ++i) inputs.push_back(getRandomInteger(0, std::numeric_limits::max())); return inputs; @@ -111,6 +115,7 @@ inline std::vector getDuplicateStringInputs(std::size_t N) { inline std::vector getRandomStringInputs(std::size_t N) { std::vector inputs; + inputs.reserve(N); for (std::size_t i = 0; i < N; ++i) inputs.push_back(getRandomString(1024)); return inputs; @@ -118,6 +123,7 @@ inline std::vector getRandomStringInputs(std::size_t N) { inline std::vector getPrefixedRandomStringInputs(std::size_t N) { std::vector inputs; + inputs.reserve(N); constexpr int kSuffixLength = 32; const std::string prefix = getRandomString(1024 - kSuffixLength); for (std::size_t i = 0; i < N; ++i) diff --git a/libcxx/test/benchmarks/atomic_wait.bench.cpp b/libcxx/test/benchmarks/atomic_wait.bench.cpp index 49503a318fda16ba02c1b92fa6bde616a15db599..d19f5fbed8ad60e449c0ecad794207d33c263aa0 100644 --- a/libcxx/test/benchmarks/atomic_wait.bench.cpp +++ b/libcxx/test/benchmarks/atomic_wait.bench.cpp @@ -9,6 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 #include +#include #include #include #include diff --git a/libcxx/test/benchmarks/atomic_wait_vs_mutex_lock.bench.cpp b/libcxx/test/benchmarks/atomic_wait_vs_mutex_lock.bench.cpp index 221fc086d2a626ff14e0143a3d3d88fe05ae0cc2..a554c721df017e6627581a6019087a75662e641d 100644 --- a/libcxx/test/benchmarks/atomic_wait_vs_mutex_lock.bench.cpp +++ b/libcxx/test/benchmarks/atomic_wait_vs_mutex_lock.bench.cpp @@ -9,8 +9,8 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 #include +#include #include -#include #include #include diff --git a/libcxx/test/benchmarks/deque.bench.cpp b/libcxx/test/benchmarks/deque.bench.cpp index b8f3b76dd27ee68d1f5da5c04e21ad3579102a41..ab0ba96b12ffca9d4a471dad11266f5a9bd5ab52 100644 --- a/libcxx/test/benchmarks/deque.bench.cpp +++ b/libcxx/test/benchmarks/deque.bench.cpp @@ -9,6 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 #include +#include #include "benchmark/benchmark.h" @@ -41,4 +42,14 @@ BENCHMARK_CAPTURE(BM_ConstructFromRange, deque_size_t, std::deque{}, get BENCHMARK_CAPTURE(BM_ConstructFromRange, deque_string, std::deque{}, getRandomStringInputs) ->Arg(TestNumInputs); +BENCHMARK_CAPTURE(BM_erase_iter_in_middle, deque_int, std::deque{}, getRandomIntegerInputs) + ->Range(TestNumInputs, TestNumInputs * 10); +BENCHMARK_CAPTURE(BM_erase_iter_in_middle, deque_string, std::deque{}, getRandomStringInputs) + ->Range(TestNumInputs, TestNumInputs * 10); + +BENCHMARK_CAPTURE(BM_erase_iter_at_start, deque_int, std::deque{}, getRandomIntegerInputs) + ->Range(TestNumInputs, TestNumInputs * 10); +BENCHMARK_CAPTURE(BM_erase_iter_at_start, deque_string, std::deque{}, getRandomStringInputs) + ->Range(TestNumInputs, TestNumInputs * 10); + BENCHMARK_MAIN(); diff --git a/libcxx/test/benchmarks/stop_token.bench.cpp b/libcxx/test/benchmarks/stop_token.bench.cpp index 6149f91c6fc3843d3d300f7fb10461a2892ec1c5..a627f80697dd5df230f9e8d828b277c18152fec5 100644 --- a/libcxx/test/benchmarks/stop_token.bench.cpp +++ b/libcxx/test/benchmarks/stop_token.bench.cpp @@ -8,7 +8,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 -#include +#include #include #include #include diff --git a/libcxx/test/benchmarks/vector_operations.bench.cpp b/libcxx/test/benchmarks/vector_operations.bench.cpp index ce8ab233fc9817bc4e44073c1f92aac7256736fa..1855861263324df1d610f3f21362ca563602e680 100644 --- a/libcxx/test/benchmarks/vector_operations.bench.cpp +++ b/libcxx/test/benchmarks/vector_operations.bench.cpp @@ -54,6 +54,16 @@ BENCHMARK_CAPTURE(BM_ConstructFromRange, vector_string, std::vector BENCHMARK_CAPTURE(BM_Pushback_no_grow, vector_int, std::vector{})->Arg(TestNumInputs); +BENCHMARK_CAPTURE(BM_erase_iter_in_middle, vector_int, std::vector{}, getRandomIntegerInputs) + ->Range(TestNumInputs, TestNumInputs * 10); +BENCHMARK_CAPTURE(BM_erase_iter_in_middle, vector_string, std::vector{}, getRandomStringInputs) + ->Range(TestNumInputs, TestNumInputs * 10); + +BENCHMARK_CAPTURE(BM_erase_iter_at_start, vector_int, std::vector{}, getRandomIntegerInputs) + ->Range(TestNumInputs, TestNumInputs * 10); +BENCHMARK_CAPTURE(BM_erase_iter_at_start, vector_string, std::vector{}, getRandomStringInputs) + ->Range(TestNumInputs, TestNumInputs * 10); + template void bm_grow(benchmark::State& state) { for (auto _ : state) { diff --git a/libcxx/test/libcxx/thread/thread.stoptoken/atomic_unique_lock.pass.cpp b/libcxx/test/libcxx/thread/thread.stoptoken/atomic_unique_lock.pass.cpp index 44d51921ac74ade334b7577a05d2717c0347a53c..a8093ae22b38dd3ff57bbeeb2df081eae36fbcee 100644 --- a/libcxx/test/libcxx/thread/thread.stoptoken/atomic_unique_lock.pass.cpp +++ b/libcxx/test/libcxx/thread/thread.stoptoken/atomic_unique_lock.pass.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "make_test_thread.h" diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index d70541290023b2303308bfa5f6baa03b3a43b12a..72fccfd3649325cf701a79abe9da1ab205b1df37 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -242,17 +242,14 @@ ccomplex utility ccomplex variant ccomplex vector ccomplex version -charconv cerrno charconv cmath charconv concepts charconv cstddef charconv cstdint charconv cstdlib charconv cstring -charconv initializer_list charconv iosfwd charconv limits -charconv new charconv type_traits charconv version chrono algorithm @@ -571,12 +568,6 @@ exception typeinfo exception version execution cstddef execution version -expected cstddef -expected cstdint -expected cstdlib -expected initializer_list -expected new -expected type_traits expected version experimental/iterator algorithm experimental/iterator atomic @@ -1340,53 +1331,6 @@ map utility map variant map vector map version -mdspan algorithm -mdspan array -mdspan atomic -mdspan bit -mdspan cctype -mdspan cerrno -mdspan cinttypes -mdspan climits -mdspan clocale -mdspan cmath -mdspan compare -mdspan concepts -mdspan cstdarg -mdspan cstddef -mdspan cstdint -mdspan cstdio -mdspan cstdlib -mdspan cstring -mdspan ctime -mdspan cwchar -mdspan cwctype -mdspan exception -mdspan functional -mdspan initializer_list -mdspan ios -mdspan iosfwd -mdspan iterator -mdspan limits -mdspan locale -mdspan memory -mdspan mutex -mdspan new -mdspan optional -mdspan ratio -mdspan span -mdspan stdexcept -mdspan streambuf -mdspan string -mdspan string_view -mdspan system_error -mdspan tuple -mdspan type_traits -mdspan typeinfo -mdspan unordered_map -mdspan utility -mdspan variant -mdspan vector mdspan version memory atomic memory cctype @@ -1416,42 +1360,15 @@ memory typeinfo memory utility memory variant memory version -memory_resource algorithm -memory_resource atomic -memory_resource bit -memory_resource cctype -memory_resource cerrno -memory_resource climits -memory_resource cmath -memory_resource compare -memory_resource concepts memory_resource cstddef memory_resource cstdint -memory_resource cstdio memory_resource cstdlib -memory_resource cstring -memory_resource ctime -memory_resource cwchar -memory_resource cwctype memory_resource exception -memory_resource initializer_list memory_resource iosfwd -memory_resource iterator -memory_resource limits -memory_resource memory -memory_resource mutex memory_resource new -memory_resource optional -memory_resource ratio memory_resource stdexcept -memory_resource string -memory_resource string_view -memory_resource system_error -memory_resource tuple memory_resource type_traits memory_resource typeinfo -memory_resource utility -memory_resource variant memory_resource version mutex algorithm mutex atomic @@ -1772,52 +1689,28 @@ random utility random variant random vector random version -ranges algorithm -ranges array -ranges atomic -ranges bit ranges cctype -ranges cerrno -ranges climits -ranges clocale ranges cmath ranges compare ranges concepts -ranges cstdarg ranges cstddef ranges cstdint ranges cstdio ranges cstdlib ranges cstring -ranges ctime ranges cwchar ranges cwctype ranges exception -ranges functional ranges initializer_list -ranges ios ranges iosfwd ranges iterator ranges limits -ranges locale -ranges memory -ranges mutex ranges new -ranges optional -ranges ratio -ranges span -ranges stdexcept -ranges streambuf -ranges string -ranges string_view -ranges system_error ranges tuple ranges type_traits ranges typeinfo -ranges unordered_map ranges utility ranges variant -ranges vector ranges version ratio climits ratio cstdint diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv index d70541290023b2303308bfa5f6baa03b3a43b12a..72fccfd3649325cf701a79abe9da1ab205b1df37 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -242,17 +242,14 @@ ccomplex utility ccomplex variant ccomplex vector ccomplex version -charconv cerrno charconv cmath charconv concepts charconv cstddef charconv cstdint charconv cstdlib charconv cstring -charconv initializer_list charconv iosfwd charconv limits -charconv new charconv type_traits charconv version chrono algorithm @@ -571,12 +568,6 @@ exception typeinfo exception version execution cstddef execution version -expected cstddef -expected cstdint -expected cstdlib -expected initializer_list -expected new -expected type_traits expected version experimental/iterator algorithm experimental/iterator atomic @@ -1340,53 +1331,6 @@ map utility map variant map vector map version -mdspan algorithm -mdspan array -mdspan atomic -mdspan bit -mdspan cctype -mdspan cerrno -mdspan cinttypes -mdspan climits -mdspan clocale -mdspan cmath -mdspan compare -mdspan concepts -mdspan cstdarg -mdspan cstddef -mdspan cstdint -mdspan cstdio -mdspan cstdlib -mdspan cstring -mdspan ctime -mdspan cwchar -mdspan cwctype -mdspan exception -mdspan functional -mdspan initializer_list -mdspan ios -mdspan iosfwd -mdspan iterator -mdspan limits -mdspan locale -mdspan memory -mdspan mutex -mdspan new -mdspan optional -mdspan ratio -mdspan span -mdspan stdexcept -mdspan streambuf -mdspan string -mdspan string_view -mdspan system_error -mdspan tuple -mdspan type_traits -mdspan typeinfo -mdspan unordered_map -mdspan utility -mdspan variant -mdspan vector mdspan version memory atomic memory cctype @@ -1416,42 +1360,15 @@ memory typeinfo memory utility memory variant memory version -memory_resource algorithm -memory_resource atomic -memory_resource bit -memory_resource cctype -memory_resource cerrno -memory_resource climits -memory_resource cmath -memory_resource compare -memory_resource concepts memory_resource cstddef memory_resource cstdint -memory_resource cstdio memory_resource cstdlib -memory_resource cstring -memory_resource ctime -memory_resource cwchar -memory_resource cwctype memory_resource exception -memory_resource initializer_list memory_resource iosfwd -memory_resource iterator -memory_resource limits -memory_resource memory -memory_resource mutex memory_resource new -memory_resource optional -memory_resource ratio memory_resource stdexcept -memory_resource string -memory_resource string_view -memory_resource system_error -memory_resource tuple memory_resource type_traits memory_resource typeinfo -memory_resource utility -memory_resource variant memory_resource version mutex algorithm mutex atomic @@ -1772,52 +1689,28 @@ random utility random variant random vector random version -ranges algorithm -ranges array -ranges atomic -ranges bit ranges cctype -ranges cerrno -ranges climits -ranges clocale ranges cmath ranges compare ranges concepts -ranges cstdarg ranges cstddef ranges cstdint ranges cstdio ranges cstdlib ranges cstring -ranges ctime ranges cwchar ranges cwctype ranges exception -ranges functional ranges initializer_list -ranges ios ranges iosfwd ranges iterator ranges limits -ranges locale -ranges memory -ranges mutex ranges new -ranges optional -ranges ratio -ranges span -ranges stdexcept -ranges streambuf -ranges string -ranges string_view -ranges system_error ranges tuple ranges type_traits ranges typeinfo -ranges unordered_map ranges utility ranges variant -ranges vector ranges version ratio climits ratio cstdint diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv index 90bff887eb27814cbac60ade4f2a86efbdbf1ed0..fd36dace19c76cc11541699aec01db441d3b8bdc 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -247,17 +247,14 @@ ccomplex utility ccomplex variant ccomplex vector ccomplex version -charconv cerrno charconv cmath charconv concepts charconv cstddef charconv cstdint charconv cstdlib charconv cstring -charconv initializer_list charconv iosfwd charconv limits -charconv new charconv type_traits charconv version chrono algorithm @@ -582,12 +579,6 @@ exception typeinfo exception version execution cstddef execution version -expected cstddef -expected cstdint -expected cstdlib -expected initializer_list -expected new -expected type_traits expected version experimental/iterator algorithm experimental/iterator atomic @@ -1370,54 +1361,6 @@ map utility map variant map vector map version -mdspan algorithm -mdspan array -mdspan atomic -mdspan bit -mdspan cctype -mdspan cerrno -mdspan cinttypes -mdspan climits -mdspan clocale -mdspan cmath -mdspan compare -mdspan concepts -mdspan cstdarg -mdspan cstddef -mdspan cstdint -mdspan cstdio -mdspan cstdlib -mdspan cstring -mdspan ctime -mdspan cwchar -mdspan cwctype -mdspan exception -mdspan execution -mdspan functional -mdspan initializer_list -mdspan ios -mdspan iosfwd -mdspan iterator -mdspan limits -mdspan locale -mdspan memory -mdspan mutex -mdspan new -mdspan optional -mdspan ratio -mdspan span -mdspan stdexcept -mdspan streambuf -mdspan string -mdspan string_view -mdspan system_error -mdspan tuple -mdspan type_traits -mdspan typeinfo -mdspan unordered_map -mdspan utility -mdspan variant -mdspan vector mdspan version memory atomic memory cctype @@ -1447,43 +1390,15 @@ memory typeinfo memory utility memory variant memory version -memory_resource algorithm -memory_resource atomic -memory_resource bit -memory_resource cctype -memory_resource cerrno -memory_resource climits -memory_resource cmath -memory_resource compare -memory_resource concepts memory_resource cstddef memory_resource cstdint -memory_resource cstdio memory_resource cstdlib -memory_resource cstring -memory_resource ctime -memory_resource cwchar -memory_resource cwctype memory_resource exception -memory_resource execution -memory_resource initializer_list memory_resource iosfwd -memory_resource iterator -memory_resource limits -memory_resource memory -memory_resource mutex memory_resource new -memory_resource optional -memory_resource ratio memory_resource stdexcept -memory_resource string -memory_resource string_view -memory_resource system_error -memory_resource tuple memory_resource type_traits memory_resource typeinfo -memory_resource utility -memory_resource variant memory_resource version mutex algorithm mutex atomic @@ -1808,53 +1723,28 @@ random utility random variant random vector random version -ranges algorithm -ranges array -ranges atomic -ranges bit ranges cctype -ranges cerrno -ranges climits -ranges clocale ranges cmath ranges compare ranges concepts -ranges cstdarg ranges cstddef ranges cstdint ranges cstdio ranges cstdlib ranges cstring -ranges ctime ranges cwchar ranges cwctype ranges exception -ranges execution -ranges functional ranges initializer_list -ranges ios ranges iosfwd ranges iterator ranges limits -ranges locale -ranges memory -ranges mutex ranges new -ranges optional -ranges ratio -ranges span -ranges stdexcept -ranges streambuf -ranges string -ranges string_view -ranges system_error ranges tuple ranges type_traits ranges typeinfo -ranges unordered_map ranges utility ranges variant -ranges vector ranges version ratio climits ratio cstdint diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv index 2f908e7f78ec151849ba861871797c239505b17d..eaec25f81e5821766e00d781e58b4cb2c5af7eae 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -571,12 +571,6 @@ exception typeinfo exception version execution cstddef execution version -expected cstddef -expected cstdint -expected cstdlib -expected initializer_list -expected new -expected type_traits expected version experimental/iterator algorithm experimental/iterator atomic @@ -1364,53 +1358,6 @@ map utility map variant map vector map version -mdspan algorithm -mdspan array -mdspan atomic -mdspan bit -mdspan cctype -mdspan cerrno -mdspan cinttypes -mdspan climits -mdspan clocale -mdspan cmath -mdspan compare -mdspan concepts -mdspan cstdarg -mdspan cstddef -mdspan cstdint -mdspan cstdio -mdspan cstdlib -mdspan cstring -mdspan ctime -mdspan cwchar -mdspan cwctype -mdspan exception -mdspan functional -mdspan initializer_list -mdspan ios -mdspan iosfwd -mdspan iterator -mdspan limits -mdspan locale -mdspan memory -mdspan mutex -mdspan new -mdspan optional -mdspan ratio -mdspan span -mdspan stdexcept -mdspan streambuf -mdspan string -mdspan string_view -mdspan system_error -mdspan tuple -mdspan type_traits -mdspan typeinfo -mdspan unordered_map -mdspan utility -mdspan variant -mdspan vector mdspan version memory atomic memory cctype @@ -1796,52 +1743,28 @@ random utility random variant random vector random version -ranges algorithm -ranges array -ranges atomic -ranges bit ranges cctype -ranges cerrno -ranges climits -ranges clocale ranges cmath ranges compare ranges concepts -ranges cstdarg ranges cstddef ranges cstdint ranges cstdio ranges cstdlib ranges cstring -ranges ctime ranges cwchar ranges cwctype ranges exception -ranges functional ranges initializer_list -ranges ios ranges iosfwd ranges iterator ranges limits -ranges locale -ranges memory -ranges mutex ranges new -ranges optional -ranges ratio -ranges span -ranges stdexcept -ranges streambuf -ranges string -ranges string_view -ranges system_error ranges tuple ranges type_traits ranges typeinfo -ranges unordered_map ranges utility ranges variant -ranges vector ranges version ratio climits ratio cstdint diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv index 1a198aa4562fdd665d0cfe8b27a2955bd3294b2a..89c28e49d6c9dec7cc5fbd83b590c6f3c8530191 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -567,12 +567,6 @@ exception typeinfo exception version execution cstddef execution version -expected cstddef -expected cstdint -expected cstdlib -expected initializer_list -expected new -expected type_traits expected version experimental/iterator algorithm experimental/iterator atomic @@ -1358,53 +1352,6 @@ map utility map variant map vector map version -mdspan algorithm -mdspan array -mdspan atomic -mdspan bit -mdspan cctype -mdspan cerrno -mdspan cinttypes -mdspan climits -mdspan clocale -mdspan cmath -mdspan compare -mdspan concepts -mdspan cstdarg -mdspan cstddef -mdspan cstdint -mdspan cstdio -mdspan cstdlib -mdspan cstring -mdspan ctime -mdspan cwchar -mdspan cwctype -mdspan exception -mdspan functional -mdspan initializer_list -mdspan ios -mdspan iosfwd -mdspan iterator -mdspan limits -mdspan locale -mdspan memory -mdspan mutex -mdspan new -mdspan optional -mdspan ratio -mdspan span -mdspan stdexcept -mdspan streambuf -mdspan string -mdspan string_view -mdspan system_error -mdspan tuple -mdspan type_traits -mdspan typeinfo -mdspan unordered_map -mdspan utility -mdspan variant -mdspan vector mdspan version memory atomic memory cctype diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index 854ad1b5df6f1ea98a6755346de37930e2d17fb0..a008b4d76edde670575aa7c48df6b197b7c6742e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -199,25 +199,15 @@ complex typeinfo complex version concepts version condition_variable atomic -condition_variable cctype condition_variable cerrno condition_variable climits -condition_variable compare condition_variable cstdint -condition_variable cstdio condition_variable cstring condition_variable ctime -condition_variable cwchar -condition_variable cwctype condition_variable initializer_list -condition_variable iosfwd condition_variable limits condition_variable new condition_variable ratio -condition_variable stdexcept -condition_variable string -condition_variable string_view -condition_variable tuple condition_variable typeinfo condition_variable version coroutine compare @@ -331,7 +321,6 @@ experimental/utility initializer_list experimental/utility limits experimental/utility utility experimental/utility version -filesystem bitset filesystem cctype filesystem cerrno filesystem climits @@ -349,7 +338,6 @@ filesystem initializer_list filesystem iomanip filesystem ios filesystem iosfwd -filesystem istream filesystem limits filesystem locale filesystem new @@ -410,13 +398,11 @@ forward_list limits forward_list new forward_list tuple forward_list version -fstream array fstream bitset fstream cctype fstream cerrno fstream climits fstream clocale -fstream cmath fstream compare fstream cstddef fstream cstdint @@ -427,7 +413,6 @@ fstream ctime fstream cwchar fstream cwctype fstream filesystem -fstream format fstream initializer_list fstream iomanip fstream ios @@ -436,9 +421,6 @@ fstream istream fstream limits fstream locale fstream new -fstream optional -fstream ostream -fstream print fstream ratio fstream stdexcept fstream streambuf @@ -463,8 +445,6 @@ functional tuple functional typeinfo functional unordered_map functional version -future array -future atomic future bitset future cctype future cerrno @@ -493,12 +473,10 @@ future stdexcept future streambuf future string future string_view -future thread future tuple future typeinfo future version initializer_list version -iomanip bitset iomanip cctype iomanip cerrno iomanip climits @@ -515,7 +493,6 @@ iomanip cwctype iomanip initializer_list iomanip ios iomanip iosfwd -iomanip istream iomanip limits iomanip locale iomanip new @@ -709,46 +686,25 @@ memory new memory tuple memory typeinfo memory version -memory_resource cctype memory_resource cerrno memory_resource climits memory_resource compare memory_resource cstdint -memory_resource cstdio -memory_resource cstring memory_resource ctime -memory_resource cwchar -memory_resource cwctype -memory_resource initializer_list -memory_resource iosfwd memory_resource limits memory_resource mutex memory_resource new memory_resource ratio -memory_resource stdexcept -memory_resource string -memory_resource string_view memory_resource tuple memory_resource typeinfo memory_resource version -mutex cctype mutex cerrno mutex climits mutex compare mutex cstdint -mutex cstdio -mutex cstring mutex ctime -mutex cwchar -mutex cwctype -mutex initializer_list -mutex iosfwd mutex limits -mutex new mutex ratio -mutex stdexcept -mutex string -mutex string_view mutex tuple mutex typeinfo mutex version @@ -951,25 +907,12 @@ set new set optional set tuple set version -shared_mutex cctype shared_mutex cerrno shared_mutex climits -shared_mutex compare shared_mutex cstdint -shared_mutex cstdio -shared_mutex cstring shared_mutex ctime -shared_mutex cwchar -shared_mutex cwctype -shared_mutex initializer_list -shared_mutex iosfwd shared_mutex limits -shared_mutex new shared_mutex ratio -shared_mutex stdexcept -shared_mutex string -shared_mutex string_view -shared_mutex tuple shared_mutex version source_location cstdint source_location version @@ -1081,13 +1024,11 @@ string_view limits string_view new string_view stdexcept string_view version -strstream array strstream bitset strstream cctype strstream cerrno strstream climits strstream clocale -strstream cmath strstream compare strstream cstddef strstream cstdint @@ -1097,7 +1038,6 @@ strstream cstring strstream ctime strstream cwchar strstream cwctype -strstream format strstream initializer_list strstream ios strstream iosfwd @@ -1105,9 +1045,6 @@ strstream istream strstream limits strstream locale strstream new -strstream optional -strstream ostream -strstream print strstream ratio strstream stdexcept strstream streambuf diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index ba2faaee5e3757a6c474e39fa2f970f3e1a74282..d5321da32b3d464d42109a89c6a588388bb84b9c 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -199,25 +199,15 @@ complex typeinfo complex version concepts version condition_variable atomic -condition_variable cctype condition_variable cerrno condition_variable climits -condition_variable compare condition_variable cstdint -condition_variable cstdio condition_variable cstring condition_variable ctime -condition_variable cwchar -condition_variable cwctype condition_variable initializer_list -condition_variable iosfwd condition_variable limits condition_variable new condition_variable ratio -condition_variable stdexcept -condition_variable string -condition_variable string_view -condition_variable tuple condition_variable typeinfo condition_variable version coroutine compare @@ -331,7 +321,6 @@ experimental/utility initializer_list experimental/utility limits experimental/utility utility experimental/utility version -filesystem bitset filesystem cctype filesystem cerrno filesystem climits @@ -349,7 +338,6 @@ filesystem initializer_list filesystem iomanip filesystem ios filesystem iosfwd -filesystem istream filesystem limits filesystem locale filesystem new @@ -410,13 +398,11 @@ forward_list limits forward_list new forward_list tuple forward_list version -fstream array fstream bitset fstream cctype fstream cerrno fstream climits fstream clocale -fstream cmath fstream compare fstream cstddef fstream cstdint @@ -426,7 +412,6 @@ fstream cstring fstream ctime fstream cwchar fstream cwctype -fstream format fstream initializer_list fstream iomanip fstream ios @@ -435,9 +420,6 @@ fstream istream fstream limits fstream locale fstream new -fstream optional -fstream ostream -fstream print fstream ratio fstream stdexcept fstream streambuf @@ -462,8 +444,6 @@ functional tuple functional typeinfo functional unordered_map functional version -future array -future atomic future bitset future cctype future cerrno @@ -492,12 +472,10 @@ future stdexcept future streambuf future string future string_view -future thread future tuple future typeinfo future version initializer_list version -iomanip bitset iomanip cctype iomanip cerrno iomanip climits @@ -514,7 +492,6 @@ iomanip cwctype iomanip initializer_list iomanip ios iomanip iosfwd -iomanip istream iomanip limits iomanip locale iomanip new @@ -708,46 +685,25 @@ memory new memory tuple memory typeinfo memory version -memory_resource cctype memory_resource cerrno memory_resource climits memory_resource compare memory_resource cstdint -memory_resource cstdio -memory_resource cstring memory_resource ctime -memory_resource cwchar -memory_resource cwctype -memory_resource initializer_list -memory_resource iosfwd memory_resource limits memory_resource mutex memory_resource new memory_resource ratio -memory_resource stdexcept -memory_resource string -memory_resource string_view memory_resource tuple memory_resource typeinfo memory_resource version -mutex cctype mutex cerrno mutex climits mutex compare mutex cstdint -mutex cstdio -mutex cstring mutex ctime -mutex cwchar -mutex cwctype -mutex initializer_list -mutex iosfwd mutex limits -mutex new mutex ratio -mutex stdexcept -mutex string -mutex string_view mutex tuple mutex typeinfo mutex version @@ -950,25 +906,12 @@ set new set optional set tuple set version -shared_mutex cctype shared_mutex cerrno shared_mutex climits -shared_mutex compare shared_mutex cstdint -shared_mutex cstdio -shared_mutex cstring shared_mutex ctime -shared_mutex cwchar -shared_mutex cwctype -shared_mutex initializer_list -shared_mutex iosfwd shared_mutex limits -shared_mutex new shared_mutex ratio -shared_mutex stdexcept -shared_mutex string -shared_mutex string_view -shared_mutex tuple shared_mutex version source_location cstdint source_location version @@ -1080,13 +1023,11 @@ string_view limits string_view new string_view stdexcept string_view version -strstream array strstream bitset strstream cctype strstream cerrno strstream climits strstream clocale -strstream cmath strstream compare strstream cstddef strstream cstdint @@ -1096,7 +1037,6 @@ strstream cstring strstream ctime strstream cwchar strstream cwctype -strstream format strstream initializer_list strstream ios strstream iosfwd @@ -1104,9 +1044,6 @@ strstream istream strstream limits strstream locale strstream new -strstream optional -strstream ostream -strstream print strstream ratio strstream stdexcept strstream streambuf diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/common.h b/libcxx/test/std/containers/sequences/vector/vector.modifiers/common.h new file mode 100644 index 0000000000000000000000000000000000000000..72cd47a50b2c0dcca152e691ecce619015cb6846 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/common.h @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// 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 TEST_STD_CONTAINERS_SEQUENCES_VECTOR_VECTOR_MODIFIERS_COMMON_H +#define TEST_STD_CONTAINERS_SEQUENCES_VECTOR_VECTOR_MODIFIERS_COMMON_H + +#include "test_macros.h" + +#include // for __libcpp_is_trivially_relocatable + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct Throws { + Throws() : v_(0) {} + Throws(int v) : v_(v) {} + Throws(const Throws& rhs) : v_(rhs.v_) { + if (sThrows) + throw 1; + } + Throws(Throws&& rhs) : v_(rhs.v_) { + if (sThrows) + throw 1; + } + Throws& operator=(const Throws& rhs) { + v_ = rhs.v_; + return *this; + } + Throws& operator=(Throws&& rhs) { + v_ = rhs.v_; + return *this; + } + int v_; + static bool sThrows; +}; + +bool Throws::sThrows = false; +#endif + +struct Tracker { + int copy_assignments = 0; + int move_assignments = 0; +}; + +struct TrackedAssignment { + Tracker* tracker_; + TEST_CONSTEXPR_CXX14 explicit TrackedAssignment(Tracker* tracker) : tracker_(tracker) {} + + TrackedAssignment(TrackedAssignment const&) = default; + TrackedAssignment(TrackedAssignment&&) = default; + + TEST_CONSTEXPR_CXX14 TrackedAssignment& operator=(TrackedAssignment const&) { + tracker_->copy_assignments++; + return *this; + } + TEST_CONSTEXPR_CXX14 TrackedAssignment& operator=(TrackedAssignment&&) { + tracker_->move_assignments++; + return *this; + } +}; + +struct NonTriviallyRelocatable { + int value_; + TEST_CONSTEXPR NonTriviallyRelocatable() : value_(0) {} + TEST_CONSTEXPR explicit NonTriviallyRelocatable(int v) : value_(v) {} + TEST_CONSTEXPR NonTriviallyRelocatable(NonTriviallyRelocatable const& other) : value_(other.value_) {} + TEST_CONSTEXPR NonTriviallyRelocatable(NonTriviallyRelocatable&& other) : value_(other.value_) {} + TEST_CONSTEXPR_CXX14 NonTriviallyRelocatable& operator=(NonTriviallyRelocatable const& other) { + value_ = other.value_; + return *this; + } + TEST_CONSTEXPR_CXX14 NonTriviallyRelocatable& operator=(NonTriviallyRelocatable&& other) { + value_ = other.value_; + return *this; + } + + TEST_CONSTEXPR_CXX14 friend bool operator==(NonTriviallyRelocatable const& a, NonTriviallyRelocatable const& b) { + return a.value_ == b.value_; + } +}; +LIBCPP_STATIC_ASSERT(!std::__libcpp_is_trivially_relocatable::value, ""); + +#endif // TEST_STD_CONTAINERS_SEQUENCES_VECTOR_VECTOR_MODIFIERS_COMMON_H diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp index 549f29a8f7ba11b6dee6860f1ce58c943ab6eb3a..f0157eb74b90f3378d5474299bb1fd728e3a1f02 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter.pass.cpp @@ -11,135 +11,79 @@ // iterator erase(const_iterator position); #include -#include #include +#include #include "asan_testing.h" +#include "common.h" #include "min_allocator.h" #include "MoveOnly.h" #include "test_macros.h" -#ifndef TEST_HAS_NO_EXCEPTIONS -struct Throws { - Throws() : v_(0) {} - Throws(int v) : v_(v) {} - Throws(const Throws& rhs) : v_(rhs.v_) { - if (sThrows) - throw 1; - } - Throws(Throws&& rhs) : v_(rhs.v_) { - if (sThrows) - throw 1; - } - Throws& operator=(const Throws& rhs) { - v_ = rhs.v_; - return *this; - } - Throws& operator=(Throws&& rhs) { - v_ = rhs.v_; - return *this; - } - int v_; - static bool sThrows; -}; - -bool Throws::sThrows = false; -#endif - -TEST_CONSTEXPR_CXX20 bool tests() { - { - int a1[] = {1, 2, 3, 4, 5}; - std::vector l1(a1, a1 + 5); - l1.erase(l1.begin()); - assert(is_contiguous_container_asan_correct(l1)); - assert(l1 == std::vector(a1 + 1, a1 + 5)); - } +template